如何从与外键相关的模型字段中动态设置字段选择?

时间:2019-05-02 21:22:27

标签: django django-models django-admin django-related-manager

我的模型为OfferWoodSliceTecJointTec。并且Wood在M2M字段中与SliceTecJointTec相关。在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

2 个答案:

答案 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)