I have a A model which uses model B and C as ForeignKeys. In A model, I want to create a constraint that lets saving only if model B and 'xyz' field in C model are unique.
When I do it as follows, it did not work. How can I achieve this?
class A(models.Model)::
B = models.ForeignKey("B", on_delete=models.CASCADE)
C = models.ForeignKey("C", on_delete=models.CASCADE)
class Meta:
unique_together = [
('B' , 'C.xyz')
]
I am not sure you can do that with unique_together.
According to django version, you can use UniqueConstraint instead so:
class Meta:
constraints = [
models.UniqueConstraint(fields=['B', 'C__xyz'], name='...')
]
Related
I can't wrap my head how to store / define the right model / relationship.
I have following data:
CATEGORY is their own model because i like to view / request in some situation only the category. But to this category I want set VALUE which I can only define onetime depending ON YYYY-MM.
What make me difficult to achieve / understand how i get the relationship between VALUE <-> YYYY-MM but still maintain the connection / dependency to only one CATEGORY "Rent".
I would look at doing something like this. You have two models with a foreign key, and value and YYYY-MM are attributes of the model with the foreign key.
class Category(models.model):
pass
class TimePeriod(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
value = models.IntegerField()
start_date = models.DateField()
class Meta:
constraints = [
models.UniqueConstraint(
fields=["category", "start_date"],
name="unique_start_date_per_category"
),
]
EDIT: Add UniqueConstraint
I want to make Django Model fields unique with two fields(values) in some conditions.
there's two fields: 'team', 'type'. And I want to make team manager unique
For Example:
team=1, type='manager'
team=1, type='manager'
-> Not available
team=1, type='manager'
team=1, type='member'
team=1, type='member'
team=2, type='manager'
-> Available
I think unique_together('team', 'type') won't work properly with this situation.
How can I make this with Django Model?
Here's my model below:
class myModel(models.Model):
team = models.ForeignKey('Team', on_delete=models.CASCADE)
type = models.CharField(max_length=10, default='member')
class Meta:
db_table = 'my_models'
I think, You need to use UniqueConstraint for your application which work perfect in kind of situation.
class myModel(models.Model):
team = models.ForeignKey('Team', on_delete=models.CASCADE)
type = models.CharField(max_length=10, default='member')
class Meta:
db_table = 'my_models'
constraints = [
models.UniqueConstraint(fields=['team', 'type'], name='unique_team')
]
you can also refer this link for more understanding. and let me know if following solution will work.
Given that there is a deprecation warning in the documentation (based on 3.2 docs) for unique_together, I think it's worth showing that this can be done using UniqueConstraint. I believe that the key missing ingredient from the previous answer is the use of UniqueConstraint.condition, like so:
from django.db import models
from django.db.models import Q, UniqueConstraint
class myModel(models.Model):
team = models.ForeignKey('Team', on_delete=models.CASCADE)
type = models.CharField(max_length=10, default='member')
class Meta:
db_table = 'my_models'
constraints = [
UniqueConstraint(
fields=['team', 'type'],
name='unique_team',
condition=Q(type='manager')
)
]
I have this model:
class MyModel(models.Model):
creation_datetime = models.DateTimeField()
expiration_datetime = models.DateTimeField()
class Meta:
constraints = [
CheckConstraint(
check=####
)
]
I am trying to write a check constraint to ensure that expiration_dateime > creation_dateime. I am unable to find a way to do it correctly with Q objects, help is appreciated.
For Django 3.1:
from django.db import models
from django.db.models import F, Q
class MyModel(models.Model):
creation_datetime = models.DateTimeField()
expiration_datetime = models.DateTimeField()
class Meta:
constraints = [
models.CheckConstraint(
check=Q(expiration_dateime__gt=F('creation_datetime')),
name="mycustomconstraint_check1"
)
]
Using F expresions: https://docs.djangoproject.com/en/3.1/ref/models/expressions/#f-expressions.
And more specific: https://docs.djangoproject.com/en/3.1/topics/db/queries/#using-f-expressions-in-filters.
Model.clean()
This method should be used to provide custom model validation, and to
modify attributes on your model if desired. For instance, you could
use it to automatically provide a value for a field, or to do
validation that requires access to more than a single field
Note, however, that like Model.full_clean(), a model’s clean()
method is not invoked when you call your model’s save() method.
https://docs.djangoproject.com/en/3.0/ref/models/instances/#django.db.models.Model.clean
Question is about using standard Django backward related manager name in DRF.
I have following serializer
class ExtraUserSerializer(serializers.ModelSerializer):
boatmodel_set = serializers.PrimaryKeyRelatedField(many=True,
queryset=BoatModel.objects.all())
class Meta:
model = get_user_model()
fields = ("id", "username", 'boatmodel_set', )
This serializer represents primary model ExtraUser and boat_model set represents backward relationship to secondary model BoatModel. Related name “boatmodel_set” chosen simply because main core Django site uses this standard “secondarymodel_set” conventional backward related manager name so that in DRF part I had to use related_name = “ boatmodel_set” as well in order to not change code in the main part.
Question is - is it possible to keep related_name = “ boatmodel_set” but represent it in rendered json as , for example “boats”??
Thank you
Yes, you can just specify the source= parameter [drf-doc], and name the field differently, like:
class ExtraUserSerializer(serializers.ModelSerializer):
boats = serializers.PrimaryKeyRelatedField(
many=True,
queryset=BoatModel.objects.all(),
source='boatmodel_set'
)
class Meta:
model = get_user_model()
fields = ('id', 'username', 'boats')
Here the JSON-side will contain "boats": ..., whereas the model side will still use myuser.boatmodel_set.all().
Given two related Django models A and B in a OneToMany relationship:
models.py
class A(models.Model):
name = models.CharField(max_length=5)
class B(models.Model):
name = models.CharField(max_length=5)
a = models.ForeignKey(A)
And given (potentially non-optimal) Tastypie resources:
api.py
class AResource(ModelResource):
bs = fields.ToManyField( 'projectname.api.BResource', 'bs', full = True)
class Meta:
queryset = A.objects.all()
class BResource(ModelResource):
a = fields.ToOneField( AResource, 'a', full = True)
class Meta:
queryset = B.objects.all()
Let's assume the database is empty so far. Now I have related external data, and would like to crowd the database it with both an instance of A and several instances of B.
What is the prettiest Tastypionic way to approach this problem? Is it possible to crowd both A and the Bs at once? Or do I need to crowd first A, and then crowd B supplying A's ID as the ForeignKey?
It would be great if someone could come up with an post example (using e.g. a python dictionary and httplib2, or curl).
Thanks a million.
The solution is here . Use the related name for tastypie fields which automatically populate the reverse relationship while creating multiple objects at once.
http://django-tastypie.readthedocs.org/en/v0.10.0/fields.html#tastypie.fields.RelatedField.related_name
RelatedField.related_name
Used to help automatically populate reverse relations when creating data. Defaults to None.
In order for this option to work correctly, there must be a field on the other Resource with this as an attribute/instance_name. Usually this just means adding a reflecting ToOneField pointing back.
Example:
class EntryResource(ModelResource):
authors = fields.ToManyField('path.to.api.resources.AuthorResource', 'author_set', related_name='entry')
class Meta:
queryset = Entry.objects.all()
resource_name = 'entry'
class AuthorResource(ModelResource):
entry = fields.ToOneField(EntryResource, 'entry')
class Meta:
queryset = Author.objects.all()
resource_name = 'author'
Use of related_name do the task. it maps the objects of related fields and automatically populates the relations when creating data.
as you did full=True on both side of your resources it will generate maximum recursion depth exceeded exception because both resources are full in each others.
Here is one solution involving ManyToMany instead of OneToMany relationships:
models.py
class B(models.Model):
name = models.CharField(max_length=5)
class A(models.Model):
name = models.CharField(max_length=5)
bs = models.ManyToManyField(B)
api.py
class BResource(ModelResource):
class Meta:
queryset = B.objects.all()
resource_name = 'b'
class AResource(ModelResource):
bs = fields.ToManyField( BResource, 'bs', related_name = 'a', full = True, null=True)
class Meta:
queryset = A.objects.all()
resource_name = 'a'
curl
curl -v -H "Content-Type: application/json" -X POST --data '{"name":"a_name1", "bs":[{"name":"b_name1"}, {"name": "b_name2"}]}' http:<my_path>/api/a/
httplib2.py
A working example to post data via a python script using the httplib2 package is based on a neat and simple solution posted by warren-runk:
post_dict(
url='http:<my_path>/api/a/',
dictionary={
'name' : 'a_name1',
'bs' : [
{'name' : 'b_name1'},
{'name' : 'b_name1'},
]
}
)
However, now an additional table to relate A and B is created in the database. There might be better solutions based on the OneToMany relationship of A and B?