首页 > 解决方案 > 在视图中动态关联子级和父级

问题描述

我有两个模型,用户模型和测量模型。Measurements 模型通过 ForeignKey 关系与 Usermodel 相关联。我已经成功地创建了允许创建用户的表单,但是希望当您查看这些用户时,您可以从那里创建测量而不指示关系,因为它应该自动使用当前显示的用户模型作为实例并关联它。这一直是个问题。我试着写这样的视图..

视图.py

def client_measurements(request, pk):
    measurement = UserModel.objects.get(id=pk)
    measurements = measurement.measurements_set.all()
    if request.method == 'POST':
        form = MeasurementsIForm(request.POST, request.FILES)

        if form.is_valid():
            form.client_name.client_name = measurement.client_name
            measure = form.save(commit=False)
            measure.instance = measurement
            measure.save()
            return HttpResponseRedirect(reverse_lazy('client', args=   [measurement.id]))
    else:
        form = MeasurementsIForm()
    return render(request, 'app/measurements.html', {'form':form,      'measurements': measurements, 'measurement': measurement}) 

这不会保存到数据库。我是 django 的新手,请问我做错了什么?

模型.py

class UserModel(models.Model):
user_name = models.ForeignKey(User, on_delete=models.CASCADE)
client_name = models.CharField(max_length=100)
# client_lname = CapitalizeCharField(max_length=100, null=True, blank=True)
address = models.CharField(max_length=500, null=True, blank=True)
MALE = 'Male'
FEMALE = 'Female'

sex = (
    (MALE, 'Male'),
    (FEMALE, 'Female'),

)

client_gender = models.CharField(
    max_length=100,
    choices=sex,
    null=True

)
tel = models.CharField(max_length=100, null=True, blank=True)
date = models.DateTimeField(auto_now_add=True, null=True)

def __str__(self):
    return self.client_name

image = models.ImageField(upload_to=image_upload, null=True, blank=True)


def save(self, *args, **kwargs):
    super().save(*args, **kwargs)

    if self.image:
        img = Image.open(self.image.path)

        if img.width > 800 or img.height > 534:
            output_size = (300, 300)
            img.thumbnail(output_size)
            img.save(self.image.path)

def get_absolute_url(self):
    return reverse('client', kwargs={'pk': self.id})


class Measurements(models.Model):
user_name = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
client_name = models.ForeignKey(UserModel, on_delete=models.CASCADE)

DRESS = 'Dress'
SHIRT = 'Shirt'
TOUSERS = 'Trousers'
SKIRT = 'Skirt'
ATIRE = 'Native Atire'
GOWN = 'Gown'

dress_type = (
    (DRESS, 'Dress'),
    (SHIRT, 'Shirt'),
    (TOUSERS, 'Trousers'),
    (SKIRT, 'Skirt'),
    (ATIRE, 'Atire'),
    (GOWN, 'Gown'),

)

cloth_type = models.CharField(
    max_length=100,
    choices=dress_type,
    null=True

)

neck = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
over_bust = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
bust = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
under_bust = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
chest = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
crutch_depth = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
ankle = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
inseam = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
total_height = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
waist = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
hips = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
neck_to_heel = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
neck_to_above_knee = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
above_knee_to_ankle = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
arm_length = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
trouser_length = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
shoulder_seem = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
arm_hole = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
bicep = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
fore_arm = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
wrist = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
v_neck_cut = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
shoulder_to_waist = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
waist_to_above_knee = models.IntegerField(validators=[MinValueValidator(1)], blank=True, null=True)
comment = models.TextField(null=True, blank=True)
date = models.DateTimeField(auto_now_add=True, null=True)
measurement_image = models.ImageField(upload_to=measurement_image_upload, null=True, blank=True)

表格.py

class ClientForm(forms.ModelForm):
client_name = forms.RegexField(regex=re.compile(r'[A-Z][a-z]+((\s[A-Z]([a-z]+)?)?)((\s[A-Z]([a-z]+)?)?)'), required=True, error_messages={'invalid': "Each name must be Capitalized. E.g 'Kelly Roland' not 'kelly roland'"}, label="Client's Full Name")
tel = forms.RegexField(regex=re.compile(r'(080|090|070|081)[0-9]{8}'), required=False, error_messages={'invalid': "Enter a valid phone number"}, label="Phone No")
class Meta:
    model = UserModel
    widgets = {
        "tel": TextInput(),
        "client_name": TextInput(attrs={"placeholder": "Emanuel Felix Johnson"})
    }
    labels = {
        "client_name": "Client's FullName",
        "tel": "Phone No",
        "client_gender": "Gender"
    }

    fields = ('client_name', 'client_gender', 'address', 'tel', 'image' )

class MeasurementsIForm(forms.ModelForm):
class Meta:
    model = Measurements
    fields = '__all__'
    exclude = ['user_name', 'client_name']

标签: pythondjangodjango-modelsdjango-forms

解决方案


这就是我如何改变你的观点来做你想做的事。请注意,模板上下文现在的客户端密钥是 user 而不是measurement.

def client_measurements(request, pk):
    client = UserModel.objects.prefetch_related('measurements_set').get(id=pk)
    measurements = client.measurements_set.all()
    if request.method == 'POST':
        form = MeasurementsIForm(request.POST, request.FILES)

        if form.is_valid():
            measurement = form.save(commit=False)
            measurement.client_name = client
            measurement.save()
            return HttpResponseRedirect(reverse_lazy('client', args=   [measurement.id]))
    else:
        form = MeasurementsIForm()
    return render(request, 'app/measurements.html', {'form':form,      'measurements': measurements, 'client': client})

顺便说一句,我强烈建议将您的测量模型更改为:

class Measurement(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    client = models.ForeignKey(UserModel, on_delete=models.CASCADE)

应该命名 ForeignKey 属性,以便表示相关模型实例,而不是它们的属性。使用 ORM 时,您应该利用抽象而不是对抗它们。


推荐阅读