Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
641 views
in Technique[技术] by (71.8m points)

python - Django模型的clean方法和FormView中的外键验证(Django model's clean method and foreign key validation in FormView)

In my django app I have simple Category and Offer models:

(在我的django应用中,我有简单的Category和Offer模型:)

class Category(BaseModel):
    title = models.CharField(_('Category title'), max_length=256)
    available = models.BooleanField(_('Is available'), default=True)
    slug = models.SlugField(max_length=256, null=True, blank=True, unique=True, verbose_name=_(Slug'))

    requires_item_price = models.BooleanField(default=False, verbose_name=_('Requires item price to be provided'))


class Offer(BaseModel):
    category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=True, verbose_name=_('Category'))


    item_price = models.DecimalField(max_digits=8, decimal_places=2, null=True, verbose_name=_('Item price'),
                                     blank=True)

    def clean(self):
        if self.category.requires_item_price and not self.item_price:
            raise ValidationError({'item_price': _('If category requires item price - you have to provide it')})

My form class:

(我的形式课:)

class NewPaginatedOfferForm(forms.ModelForm):
    class Meta:
        model = Offer
        fields = ('item_price',)

    def __init__(self, category, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.category = category
        self.helper = FormHelper()
        self.helper.form_id = self.__class__.__name__.lower()
        self.initial['category'] = category

        self.helper.layout = Layout(
            Field('item_price'),
            Div(
                Submit('submit', _(Save →'),
                       css_class="btn btn-lg bold btn-block btn-success", ),
            )
        )

and my view class, based on generic CreateView class:

(和我的视图类,基于通用的CreateView类:)

class NewOfferForCategoryView(CreateView):
    model = Offer
    category = None
    template_name = 'web/new_offer_for_category.html'

    def get_form_class(self):
        print('get_form_class')
        if self.category.requires_item_price:
            return NewPaginatedOfferForm

    def get_form_kwargs(self):
        print('get_form_kwargs')
        kwargs = super().get_form_kwargs()
        kwargs['category'] = self.category
        print('kwargs:', kwargs)
        return kwargs

    def dispatch(self, request, *args, **kwargs):
        print('dispatch, ', request.method)
        try:
            self.category = Category.objects.get(slug=self.kwargs.get('cat_slug'), available=True)
        except:
            print('wrong category')
            return redirect(reverse('web:new_offer'))
        print('self category is', self.category)
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        print('form_valid')
        form.instance.category = self.category
        return super().form_valid(form)

    def form_invalid(self, form):
        print('form_invalid')
        form.instance.category = self.category
        return super().form_invalid(form)

    def get_context_data(self, **kwargs):
        print('get_context_data')
        ctx = super().get_context_data(**kwargs)
        ctx['categories'] = Category.objects.filter(available=True)
        ctx['category'] = self.category
        return ctx

GET requests are working fine.

(GET请求工作正常。)

Problem is when I try to submit such form.

(问题是当我尝试提交此类表格时。)

I am always getting an error:

(我总是遇到错误:)

AttributeError at /new-offer/my-category-slug
'NoneType' object has no attribute 'requires_item_price'

Request Method: POST
Request URL:    http://127.0.0.1:8000/new-offer/my-category-slug
Django Version: 2.2.6
Exception Type: AttributeError
Exception Value:    
'NoneType' object has no attribute 'requires_item_price'
Exception Location: /Users/User/project/core/models.py in clean, line 272

Looks like category property is None in Offer model clean method - but I am not sure why and how can I pass it there.

(看起来在Offer模型清除方法中category属性为None,但是我不确定为什么以及如何将其传递给它。)

I want to use model clean method as it covers also django's admin panel validation when new object is created there.

(我想使用模型清理方法,因为当在其中创建新对象时,它也涵盖了django的管理面板验证。)

Any ideas?

(有任何想法吗?)

  ask by dease translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...