我的模型为Offer
,Wood
,SliceTec
和JointTec
。并且Wood
在M2M字段中与SliceTec
和JointTec
相关。在Django管理员处,添加新的Wood记录时,我可以为 SliceTec 和 JointTec 选择多个选项。没问题。当涉及要约时,我需要显示来自所选 Wood 记录 woodSlice 数据以及 woodJoint 数据的选项。
例如;
SliceTec数据:切片A,切片B,切片C
JointTec数据:Jointt A,Joint B,Joint C
木材数据:木材A,(切片A,切片C),(接合B,接头C)
在Offer
,选择 Wood A 后,我需要显示切片A 和切片B 选项。
class Offer(models.Model):
name = models.CharField(max_length=200, verbose_name='Adınız Soyadınız')
phone = models.BigIntegerField(verbose_name='Telefon Numaranız')
email = models.EmailField(verbose_name='E-mail Adresiniz')
date = models.DateTimeField(verbose_name='Teklif Tarihi')
frontWood = models.ForeignKey('Wood', on_delete=models.PROTECT)
frontSlice = models.CharField(max_length=200)
frontJoint = models.CharField(max_length=200)
frontSupport = models.ForeignKey('Support', on_delete=models.PROTECT)
frontThick = models.CharField(max_length=200)
frontDimen = models.CharField(max_length=200)
frontFlow = models.ForeignKey('Flow', on_delete=models.PROTECT)
frontGlue = models.ForeignKey('Glue', on_delete=models.PROTECT)
class Meta:
verbose_name = 'Teklif Talebi'
verbose_name_plural = 'Teklif Talepleri'
def __str__(self):
return self.name
class Wood(models.Model):
woodName = models.CharField(max_length=200, verbose_name='Ahşap Adı')
woodCode = models.CharField(max_length=50, verbose_name='Stok Kodu', blank=True, null=True)
woodSlice = models.ManyToManyField('SliceTec', verbose_name='Uygun Kesim Teknikleri')
woodJoint = models.ManyToManyField('JointTec', verbose_name='Uygun Ekleme Teknikleri')
woodImage = models.ImageField(verbose_name='Görsel', blank=True, null=True)
woodPrice = models.PositiveIntegerField(verbose_name='Fiyat Düzeyi', blank=True, null=True)
woodDesc = models.TextField(verbose_name='Açıklama', blank=True, null=True)
class Meta:
verbose_name = 'Ahşap Türü'
verbose_name_plural = 'Ahşap Türleri'
def __str__(self):
return self.woodName
class SliceTec(models.Model):
sliceName = models.CharField(max_length=200, verbose_name='Kesim Tekniği Adı')
sliceImage = models.ImageField(verbose_name='Görsel', blank=True, null=True)
sliceDesc = models.TextField(verbose_name='Açıklama', blank=True, null=True)
class Meta:
verbose_name = 'Kesim Tekniği'
verbose_name_plural = 'Kesim Teknikleri'
def __str__(self):
return self.sliceName
class JointTec(models.Model):
jointName = models.CharField(max_length=200, verbose_name='Ekleme Tekniği Adı')
jointImage = models.ImageField(verbose_name='Görsel', blank=True, null=True)
jointDesc = models.TextField(verbose_name='Açıklama', blank=True, null=True)
class Meta:
verbose_name = 'Ekleme Tekniği'
verbose_name_plural = 'Ekleme Teknikleri'
def __str__(self):
return self.jointName
答案 0 :(得分:0)
如果要制作单个表单,除非我缺少某些内容,否则将无法执行此操作,因为渲染表单时您不知道选择了哪种木材。
您可以尝试使用javascript在页面内实现逻辑
答案 1 :(得分:0)
您可以使用以下代码在管理员中更改标签。
将此添加到您的Wood模型中:
public class GalleryFragment extends Fragment {
private static final String TAG = "GalleryFragment";
//constants
private static final int NUM_GRID_COLUMNS = 3;
//widgets
private GridView gridView;
private ImageView galleryImage;
private ProgressBar mProgressBar;
private Spinner directorySpinner;
//vars
private ArrayList<String> directories;
private String mAppend = "file:/";
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_gallery, container, false);
galleryImage = (ImageView) view.findViewById(R.id.galleryImageView);
gridView = (GridView) view.findViewById(R.id.gridView);
directorySpinner = (Spinner) view.findViewById(R.id.spinnerDirectory);
mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar);
mProgressBar.setVisibility(View.GONE);
directories = new ArrayList<>();
Log.d(TAG, "onCreateView: started.");
ImageView shareClose = (ImageView) view.findViewById(R.id.ivCloseShare);
shareClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick: closing the gallery fragment.");
getActivity().finish();
}
});
TextView nextScreen = (TextView) view.findViewById(R.id.tvNext);
nextScreen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick: navigating to the final share screen.");
}
});
init();
return view;
}
private void init(){
FilePaths filePaths = new FilePaths();
//check for other folders indide "/storage/emulated/0/pictures"
if(FileSearch.getDirectoryPaths(filePaths.PICTURES) != null){
directories = FileSearch.getDirectoryPaths(filePaths.PICTURES);
}
directories.add(filePaths.CAMERA);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_spinner_item, directories);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
directorySpinner.setAdapter(adapter);
directorySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "onItemClick: selected: " + directories.get(position));
//setup our image grid for the directory chosen
setupGridView(directories.get(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
private void setupGridView(String selectedDirectory){
Log.d(TAG, "setupGridView: directory chosen: " + selectedDirectory);
final ArrayList<String> imgURLs = FileSearch.getFilePaths(selectedDirectory);
//set the grid column width
int gridWidth = getResources().getDisplayMetrics().widthPixels;
int imageWidth = gridWidth/NUM_GRID_COLUMNS;
gridView.setColumnWidth(imageWidth);
//use the grid adapter to adapter the images to gridview
GridImageAdapter adapter = new GridImageAdapter(getActivity(), R.layout.layout_grid_imageview, mAppend, imgURLs);
gridView.setAdapter(adapter);
//set the first image to be displayed when the activity fragment view is inflated
setImage(imgURLs.get(0), galleryImage, mAppend);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "onItemClick: selected an image: " + imgURLs.get(position));
setImage(imgURLs.get(position), galleryImage, mAppend);
}
});
}
private void setImage(String imgURL, ImageView image, String append){
Log.d(TAG, "setImage: setting image");
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(append + imgURL, image, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
mProgressBar.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
mProgressBar.setVisibility(View.INVISIBLE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
mProgressBar.setVisibility(View.INVISIBLE);
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
mProgressBar.setVisibility(View.INVISIBLE);
}
});
}
}
然后在管理员中,您可以覆盖OfferAdmin的ComponentForm
def description(self):
slice_names = ','.join(self.woodSlice.values_list('sliceName', flat=True))
joint_names = ','.join(self.woodJoint.values_list('jointName', flat=True))
return '{}, (), ()'.format(self.woodName, slice_names, joint_names)