I need to make a queryset on django and I want to filter both a model and its related model. Like I need to get all PartRequest's that are created by a seller and I want to retrieve only his bid attatched.
class PartRequest(models.Model):
class Bid(models.Model):
seller = models.ForeignKey(UserSeller, related_name='seller_bid')
request = models.ForeignKey(PartRequest, related_name='request_bid')
If I understand correctly this is what you want
bids = Bid.objects.filter(seller=your seller here)
partRequests = bids.values_list('request', flat=True)
You can't get it as an instance of a particular model if you want it as a single object. Take a look at raw() for what you want.
https://docs.djangoproject.com/en/dev/topics/db/sql/
Related
I have one model called Weight (filled by User input/choice) and another called Enterprise.
class Weight(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="weights")
weight_of_history = models.IntegerField(null=True, blank=True)
class Enterprise(models.Model):
...
The weight is saved, one per user, and replaced everytime the user choose new one.
Inside the Enterprise class, I am creating an property that must get the "weight_of_history" (depending on the user, who has chosen the weight) from Weight class, but the models have no Foreign key or related name between them.
class Enterprise(models.Model):
...
#property
def ranking(self):
weight_of_history = <-- HERE I NEED TO TAKE WEIGHT_HISTORY FROM THE FIRST MODEL
THEN I COULD CALCULATE
How could I do that? Thank you!
You can use django's powerful query functionality and fetch the required objects from the db. Here are the docs that might help you with that. Django docs are amazing, so I would recommend that you read up on queries, models, and forms to have easier time with you project.
For your example we can fetch all the weights for the user in one query by filtering the weights by user. In fact, django ORM allows for chaining filters and you can create really sophisticated queries
class Enterprise(models.Model):
...
#property
def ranking(self):
weight_of_history = Weight.objects.filter(user=some_user)
If you do not know the user beforehand, then you can do inside the view and grab the user that makes the request and filter using this user:
#views.py
user_making_request = request.user
weight_of_history = Weight.objects.filter(user=user_making_request)
I have built an Angular form that contains a form array. So the user has the control to add fields or delete fields from the form. What I am trying to understand is how I can design a Django API that can handle the post for this kind of dynamic form?
I do not want the user to create an account on the website in order to place his order. Is that even possible?
You should be more concerned about how to model your data, than you can think about your interface. Here a few options for modeling your data:
Option One is to use regular Django ORM, and in this case you may use the JSONField for any dynamic properties.
Option two is to use any schemaless data model, such as document-based databases(e.g MongoDB).
Here a simple example, on how to use Django's JSONField:
your model:
class Order(models.Model):
customer = models.ForeignKey(User, on_delete=models.CASCADE)
#any additional static fields
properties = JSONField()
your view:
def create_order_view(request):
if request.method == "POST":
#do your validation
Order.objects.create(user=request.user, properties=request.POST["properties"])
return Response(status=200)
this example is totally incomplete as you have to add validation error handling, and it is a better idea to use Django rest-framework for constructing your API.
Finally as I said there many option to model your data, in addition to what I mentioned above there are many other. To decide what model to use, you have to know how your data gonna be consumed, so you can optimze for query time, in addition there are many other factors but this is out of scope of this asnwer.
For me, I used Django-RESTframework to build the api.
The way to achieve this is simple, just create the model and iterate through the items which is the dynamic part, and assign the Foreignkey field to obj.id created. First, I created the main model instance, then created the instances of the child instances. I will use Order and Item to demonstrate the idea, The Item instance will have Foreinkey field to Order model.
In the Item model, add "related_name" argument to the Foreinkey field
order = models.ForeignKey(Order, related_name='items',on_delete=models.CASCADE)
serializers.py
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = [
....your fields...
]
class OrderSerializer(serializers.ModelSerializer):
items = ItemSerializer(many=True)
class Meta:
model = Order
fields = [
'order', ....
]
def create(self, validated_data):
items_data = validated_data.pop("items")
order = Order.objects.create(**validated_data)
order.total_fees = order.delivery_fees
for item in items_data:
i = Item.objects.create(order=order, **item)
return order
I have large table of data (~30 Mb) that I converted into into a model in Django. Now I want to have access to that data through a REST API.
I've successfully installed the Django REST framework, but I'm looking for a way to automatically create a URL for each field in my model. My model has about 100 fields, and each field has about 100,000 entries.
If my model is named Sample,
models.py
class Sample(models.Model):
index = models.IntegerField(primary_key=True)
year = models.IntegerField(blank=True, null=True)
name = models.TextField(blank=True, null=True)
...97 more fields...
then I can access the whole model using Django REST framework like this:
urls.py
class SampleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Sample
fields = ( **100 fields**)
class SampleViewSet(viewsets.ModelViewSet):
queryset = Sample.objects.all()
serializer_class = SampleSerializer
router = routers.DefaultRouter()
router.register(r'sample', SampleViewSet)
But of course my browser can't load all of that data in a reasonable amount of time. I could manually make a different class and URL for each field, but there must be a better way... I want to be able to go to my_site.com/sample/year (for example) and have it list all of the years in JSON format, or my_site.com/sample/name and list all the names, etc.
Please help me figure out how to do this, thanks!
You might be able to do that using a custom viewset route.
You have this:
class ModelViewSet(ModelViewSet):
#list_route()
def sample_field(self, request):
desired_field = request.data.get('field', None)
if not desired_field:
return response # pseudocode
values = Model.objects.all().values_list(desired_field, flat=True)
# serialize this for returning the response
return Response(json.dumps(values)) # this is an example, you might want to do something mode involved
You will be able to get this from the url:
/api/model/sample_field/?field=foo
This extra method on the viewset will create a new endpoint under the samples endpoint. Since it's a list_route, you can reach it using /sample_field.
So following your code, it would be:
mysite.com/sample/sample_field/?field='year'
for example.
There are many interesting details in your question, but with this sample I think you might able to achieve what you want.
Try to use pagination. You can do it in almost the same way as in you question. Pagination in django lets you divide the results into pages. You don't have to display all the entries in the same page. I think this is the best option for you.
Refer django documentation on pagination:
Pagination in django
I have been countering a problem of retrieving a 'sub' objects from an objects list:
class BusinessLike(models.Model):
user = models.ForeignKey(AppUser, related_name='user_business_likes')
business = models.ForeignKey(Business, related_name='business_likes')
class Meta:
unique_together = (('user', 'business'),)
How do I get 'Business' object for each 'BusinessLike' object in app_user.user_businesses_likes (without looping over the list and making new list with business_like.business)?
You can use values or values_list:
businesses = BusinessLike.objects.values('business')
businesses = BusinessLike.objects.values_list('business', flat=True)
However, this won't give you a list of objects, you only get a list of foreign key ids.
Django doc about values and value_list.
If you want to avoid having additional lookups every time you do business_like.business, you could use select_related:
business_likes = BusinessLike.objects.select_related('business')
In this case, when you loop on each BusinessLike object and do business_like.business, django won't join the database anymore but it's cached in memory already.
Django doc about select_related.
If you are doing this in the view, you might find it easier to make a new queryset starting with the Business model.
businesses = Business.objects.filter(business_likes__user=app_user)
I'm not sure that you need to create the BusinessLike model like this. You could add a many to many field to the AppUser model (or the Business model if you prefer).
class AppUser(models.Model):
business_likes = models.ManyToManyField(Business)
Django will take care of creating the intermediate table, and then you can do queries like:
businesses = app_user.business_likes.all()
I have the following situation. I have three models, Post, User and Friends.
class User(models.Model):
name = models.CharField(max_length=100)
class Friend(models.Model):
user1 = models.ForeignKey(User,related_name='my_friends1')
user2 = models.ForeignKey(User,related_name='my_friends2')
class Post(models.Model):
subject = models.CharField(max_length=100)
user = models.ForeignKey(User)
Every time I bring users, I want to bring the number of his friends:
User.objects.filter(name__startswith='Joe').annotate(fc=Count('my_friends1'))
This works fine.
However, I want to make this work when I bring the users as nested objects of Post. I'm using there select_related to minimized DB calls, so I want to do something like:
Post.objects.filter(subject='sport').select_related('user').annotate(user__fc=Count('user__my_friends1'))
However, this creates field user__fc under post, and not field fc under post.user.
Is there a way to achieve this functionality?
You can make use of Prefetch class:
from django.db.models import Count, Prefetch
posts = Post.objects.all().prefetch_related(Prefetch('user', User.objects.annotate(fc=Count('my_friends1'))))
for post in posts:
print(post.subject)
print(post.user.fc)
NB : this does two database queries (Django does the join between Post and User in this case) :
'SELECT "myapp_post"."id", "myapp_post"."subject", "myapp_post"."user_id" FROM "myapp_post"
'SELECT "myapp_user"."id", "myapp_user"."password", "myapp_user"."last_login", "myapp_user"."is_superuser", "myapp_user"."username", "myapp_user"."first_name", "myapp_user"."last_name", "myapp_user"."email", "myapp_user"."is_staff", "myapp_user"."is_active", "myapp_user"."date_joined", COUNT("myapp_friend"."id") AS "fc" FROM "myapp_user" LEFT OUTER JOIN "myapp_friend" ON ("myapp_user"."id" = "myapp_friend"."user1_id") WHERE "myapp_user"."id" IN (3, 4) GROUP BY "myapp_user"."id", "myapp_user"."password", "myapp_user"."last_login", "myapp_user"."is_superuser", "myapp_user"."username", "myapp_user"."first_name", "myapp_user"."last_name", "myapp_user"."email", "myapp_user"."is_staff", "myapp_user"."is_active", "myapp_user"."date_joined"
You can define a custom manger for your models, as described here and then override its get_queryset() method to add the custom column to your model upon query.
In order to use this manager for a reverse relation, you should set the base manager as described in the docs.
Another approach would be something like this, which you specify the manager of the related model with a hard-coded attribute.