get()返回多个孩子 - 它返回2!在django

时间:2016-11-07 07:55:55

标签: python django forms

我有一个链接模型:

class Children(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    child_name = models.CharField(max_length=150, null=True, blank=True)
    slug = AutoSlugField(populate_from='child_name')
    blood_group = models.CharField(max_length=5, blank=True)

   class Meta:
          unique_together = ('slug', 'person')

def get_absolute_url(self):
    return self.person.get_absolute_url()

def get_delete_url(self):
    return reverse(
        'member:children-delete',
        kwargs={
            'person_slug': self.person.slug,
            'children_slug': self.slug})

def get_update_url(self):
    return reverse(
        'member:children-update',
        kwargs={
            'person_slug': self.person.slug,
            'children_slug': self.slug})

my forms.py:

class ChildrenForm( SlugCleanMixin, forms.ModelForm):

    class Meta:
        model = Children
        exclude = ('person',)

    def clean(self):
        cleaned_data = super().clean()
        slug = cleaned_data.get('slug')
        person_obj = self.data.get('person')
        exists = (
            Children.objects.filter(
                slug__iexact=slug,
                person=person_obj,
            ).exists())
        if exists:
            raise ValidationError(
                "Children with this Slug "
                "and Person already exists.")
        else:
            return cleaned_data

    def save(self, **kwargs):
        instance = super().save(commit=False)
        instance.person = (
            self.data.get('person'))
        instance.save()
        self.save_m2m()
        return instance

views.py:

class ChildrenCreate( ChildrenFormMixin, ChildrenGetObjectMixin,
    PersonContextMixin,CreateView):
    template_name = 'member/children_form.html'
    model = Children
    form_class = ChildrenForm


class ChildrenUpdate(ChildrenFormMixin, ChildrenGetObjectMixin,
    PersonContextMixin,UpdateView):
    template_name = 'member/children_form.html'
    model = Children
    form_class = ChildrenForm
    slug_url_kwarg = 'children_slug'        



class ChildrenDelete(ChildrenFormMixin,ChildrenGetObjectMixin,
    PersonContextMixin,DeleteView):
    model = Children
    slug_url_kwarg = 'children_slug'

    def get_success_url(self):
        return (self.object.person
                .get_absolute_url())

my utils.py:

class ChildrenFormMixin():

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        if self.request.method in ('POST', 'PUT'):
            self.person = get_object_or_404(
                Person,
                slug__iexact=self.kwargs.get(
                    self.person_slug_url_kwarg))
            data = kwargs['data'].copy()
            data.update({'person': self.person})
            kwargs['data'] = data
        return kwargs

class ChildrenGetObjectMixin():

    def get_object(self, queryset=None):
        person_slug = self.kwargs.get(
            self.person_slug_url_kwarg)
        children_slug = self.kwargs.get(
            self.slug_url_kwarg)
        return get_object_or_404(
            Children,
            slug__iexact=children_slug,
            person__slug__iexact=person_slug)

class PersonContextMixin():
    person_slug_url_kwarg = 'person_slug'
    person_context_object_name = 'person'

    def get_context_data(self, **kwargs):

        person_slug = self.kwargs.get(
            self.person_slug_url_kwarg)
        person = get_object_or_404(
            Person, slug__iexact=person_slug)
        context = {
            self.person_context_object_name:
                person,
        }
        context.update(kwargs)
        return super().get_context_data(**context)

孩子们为同一个父母的同名创造了不止一个。当我尝试编辑子项时,会出现"get() returned more than one Children -- it returned 2!"错误。在追溯中,它说,'person__slug__iexact=person_slug'是这种追溯的直接原因。

在表单中,我添加了清除方法来捕获错误并保持同一父母的子名称的唯一性,但它没有工作。我可以在错误的地方得到建议吗?

编辑:

我的人物模型:

class Person(models.Model):
    name = models.CharField(max_length=250)
    slug = AutoSlugField(populate_from='name')
    birth_date = models.DateField(null=True, blank=True)
    blood_group = models.CharField(max_length=5)
    present_address = models.CharField(max_length=250, blank=True)
    permanent_address = models.CharField(max_length=250, blank=True)
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        related_name='member_persons')

    class Meta:
       ordering = ['name']
       unique_together = ['name', 'birth_date']

1 个答案:

答案 0 :(得分:0)

我相信您正在使用AutoSlugField中的django-autoslug,而您试图通过非唯一字段获取。默认情况下,AutoSlugField不会使您的字段唯一,来自docs:

  

AutoSlugField还可以在保存时执行以下任务:

     
      
  • 从另一个字段填充自己(使用populate_from),
  •   
  • 使用自定义slugify功能(使用slugify或设置)和
  •   
  • 保留值的唯一性(使用unique或unique_with)。
  •   
     

这些任务都不是强制性的,即您可以拥有自动填充的非唯一字段,手动输入的唯一字段(绝对唯一或在给定日期内)或两者都有。

快速修复slug = AutoSlugField(populate_from='child_name', unique=True)

更新(自您发布了Person模型)

问题是一样的,解决方案是一样的。

说明:

例如,您有两个Person个对象:

id name  slug  birth_date
1  alex  alex  10.10.2016
2  alex  alex  10.10.2015

这不会违反unique_together = ['name', 'birth_date']

你有两个Children个对象:

id name slug person_id
1  john john 1
2  john john 2

这不会违反unique_together = ('slug', 'person')

然后你正在进行查询

get_object_or_404(
            Children,
            slug__iexact='john',
            person__slug__iexact='alex')

哪个匹配两个对象。所以你遇到了问题。快速解决方法是制作slu unique=True