Django: Get each user Invoices, Expenses, Withdrawals. (ORM) relationship - python

I've been stuck for a couple of hours, and can't figure out the correct way to do it. So basically I know that looping is not a really good practice, because if we would have a lot of users, the system would start time outing. So my idea is to pick the correct way to get the things that I need.
This is our core scheme:
I need to make this kind of 'table', and these are the things that I need:
This is the thing that will be displayed in our Front-End, so for now, I only need to collect the correct data and pass it into our FE. We use celery tasks, so the timing is always set (Mondays at 6 PM for ex.)
This is what I've tried so far..
for user in User.objects.all():
start_date = timezone.now() - timedelta(weeks=1)
# How to loop correctly over every user and check for invoices??
invoices = InvoiceItem.objects.select_related('invoice', 'invoice__operation_ptr_id')
# invoices[0].operation_ptr_id ???
The looping for user in User.objects.all() should probably be replaced to annotate. How can I make the relationship to get invoices, withdrawals, expenses?

Try querying from the User instead of InvoiceItem models
I'm not sure what specifically you need to return to the frontend, but if needed, returning the actual values should be quite easy after doing some annotations
To get the number of invoices of a user try this:
from django.db.models import Count
User.objects.annotate(total_invoices=Count("invoices"))
As for withdrawals and expenses, it seems like those models don't have a relationship with the User model at all. I would suggest updating your models to add a relationship between them, and query them similarly like the query above.
I'm also making the assumption that User = Customer, since you didn't actually provide the Customer model in your other post.

Related

When to use an abstract model?

There's a form on our website that gives you a quote if you enter a to and from address. From there, you can go ahead and make a booking or just leave the website. We save the quotes generated by users for statistic purposes (e.g compare the quote and booking ratio). Currently, I use two tables for this. Quotation and Booking. Here are the tables (models in Django):
Quotation:
to
from
price
some_charge
other_charge
Booking:
to
from
price
some_charge
other_charge
name
# other booking details
I have kept them as separate models but I have noticed they are getting very similar over time. I am adding fields to both models and also have duplicate methods. Should I make a QuotationModel and extend both from that? Any other suggestions? Any theory I should for a scenario like this?

How can i save a form without a submit button in django

i have a doubt, i want to save a form and without use a submit button.
Because, as you´ll see:
i need to increase "cantidad" but i don't want to use a "sumbmit" button, otherwise, i need that the data (integers) will stay correctly in a database field.
Because, in my models.py i have:
cantidad = models.IntegerField(default=0)
I want to modify the field 'cantidad' when the user increase or decrease Selection, as you see in the image and without a submit button.
Is there a way to do this?
Any help thank you!.
After talking to you, something like this will work, but you'll have to modify it to your needs. I would use sessions because their values are stored without having to save your current modelfield in the database, and users could still browse the site without having to update the values every time.
Remember: Sessions are accessible like dictionaries. But you have to .save() them just like you would any model, because it's still a model stored in the database. The reason you should use these instead of your product model is because sessions are intended to be random, and are easy to clear with python manage.py clearsessions. If you used your own model, assuming you have thousands of models to dig through which were never purchased by someone, this is FAR EASIER and faster, and keeps your database cleaner.
This is a quick answer, though I suggest you implement a shopping cart that's already been made by someone else. Check djangopackages.org for some good ones. What they have will be better than what I'm about to show you, though this is the principle you follow either way.
GENERAL STEPS TO TAKE:
Make a session key: request.session['cart'] = {}
Add keys and values to it: request.session['cart']['product_id'] = 111
Add more values to that product: request.session['cart']['quantity'] = 222
Save it: request.session.save()

Django Rest Framework Pagination Since ID

I have built an API with Django Rest Framework. I want to change pagination for a better user experience.
The problem:
The client makes a call to request all posts. The request looks like:
http://website.com/api/v1/posts/?page=1
This returns the first page of posts. However, new posts are always being created. So when the user requests:
http://website.com/api/v1/posts/?page=2
The posts are almost always the same as page 1 (since new data is always coming in and we are ordering by -created).
Possible Solution?
I had the idea of sending an object id along with the request so that when we grab the posts. We grab them with respect to the last query.
http://website.com/api/v1/posts/?page=2&post_id=12345
And when we paginate we filter where post_id < 12345
But this only works assuming our post_id is an integer.
Right now I'm currently only using a basic ListAPIView
class PostList(generics.ListAPIView):
"""
API endpoint that allows posts to be viewed
"""
serializer_class = serializers.PostSerializer # just a basic serializer
model = Post
Is there a better way of paginating? so that the next request for that user's session doesn't look like the first when new data is being created.
You're looking for CursorPagination, from the DRF docs:
Cursor Pagination provides the following benefits:
Provides a consistent pagination view. When used properly CursorPagination ensures that the client will never see the same item twice when paging through records, even when new items are being inserted by other clients during the pagination process.
Supports usage with very large datasets. With extremely large datasets pagination using offset-based pagination styles may become inefficient or unusable. Cursor based pagination schemes instead have fixed-time properties, and do not slow down as the dataset size increases.
You can also use -created as the ordering field as you mentioned above.
How about caching the queryset? So that the next page is served from the same query set, and not from a new one. And then you could use a parameter to get a new queryset when you want.
Something like this:
from django.core.cache import cache
class PostList(generics.ListAPIView):
def get_queryset(self):
qs_key = str(self.request.user.id) + '_key'
if 'refresh' in self.request.QUERY_PARAMS:
# get a new query set
qs = Post.objects.all()
cache.set(qs_key, qs)
return cache.get(qs_key)
So basically, only when your url will be like this:
http://website.com/api/v1/posts/?refersh=whatever
the request will return new data.
UPDATE
In order to provide each user with it's own set of posts, the cache key must contain an unique identifier (which might be the user's ID):
I also updated the code.
The downside to this approach is that for a very large number of users and a large number of posts for each user, it might not work very well.
So, here is my second idea
Use a TimeStamped model for the Post model, and filter the query set based on the created field.
I don't know much about your models and how exactly they are built, so I guess you will have to choose which solution is best for your app :)
Maybe you can add a field to every object like "created_at/updated_at". Then you can save the timestamp when the user made the request and filter out everything that came after it.
Haven't tried it myself but I guess it might work on your case

Django GenericForeignKey lookup for a given model

I use a voting app (django-ratings if that makes any difference) which uses django's GenericForeignKey, has a ForeignKey to User, and several other fields like date of latest change.
I'd like to get all the objects of one content type, that a single user voted for ordered by date of latest change. As far as I understand - all the info can be found in a single table (except the content_type which can be prefetched/cached). Unfortunately django still makes an extra query each time I request a content_object.
So the question is - how do I get all the votes on a given model, by a given user, with related objects and given ordering with minimum database hits?
Edit: Right now I'm using 2 queries - first selecting all the votes, getting all the objects I need, filtering by .filter(pk__in=obj_ids) and finally populating them to votes objects. But it seems that a reverse generic relation can help solve the problem
Have you checked out select_related()? That may help.
Returns a QuerySet that will automatically "follow" foreign-key relationships, selecting that additional related-object data when it executes its query. This is a performance booster which results in (sometimes much) larger queries but means later use of foreign-key relationships won't require database queries.
https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related
Well right now we're using prefetch_related() from django 1.4 on a GenericRelation. It still uses 2 queries, but has a very intuitive interface.
From looking at the models.py of the django-ratings app, I think you would have to do user.votes.filter(content_type__model=Model._meta.module_name).order_by("date_changed") (assuming the model you want to filter by is Model) to get all the Vote objects. For the related objects, loop through the queryset getting content_object on each item. IMHO, this would result in the least DB queries.

Design ideas for a webapp in Django

I'm working on a user based, social networking type of web application in Django. It's my first one so I would like to make sure I'm using some good practices.
Currently the web app supports two kinds of users. This is represented by two different Groups. When I register a user I assign them to one of these two groups. I also have two apps, one for each type of user. The apps handle whatever things are distinct to a particular type of user. I have another app that handles the actual authentication. This app uses Django's built in User type and assigns them a UserProfile. The two different types of users have their own profiles which extend/inherit from UserProfile.
This works reasonably well, and is fairly reusable since the authentication app can pull the user type from the url and figure out which type of user to create. Since the groups are named conveniently, they can be added to the correct group too.
Is this the best way or are there more preferred, tried and true ways to handle this? It seems like a pretty common enough scenario. I don't want to continue incorrectly reinventing the wheel if I don't have to.
I was thinking of adding another app called, common, or something which would handle things that are common to all users. For example, viewing a users profile page might be something anyone who is logged in might want to do, regardless of what type of user they are.
Thanks!
Easy part first, with 2) you're spot on. That would be the simplest and most effective way of doing that. It makes sense instead of replicating functionality across both applications to have one app that handles things that are common to both user types.
Back to 1)
With both profiles extending from UserProfile, you'd run into the issue of (if you were using get_profile() on a User object - see http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users) that you'd get back just a UserProfile object, not knowing which group the user actually belongs to based on the object received. This is because they both extend UserProfile but UserProfile would not be able to be (I believe) abstract, because you want every User to have a pointer to a UserProfile object which may actually be a UserGroup1 or a UserGroup2 object.
What I would suggest you do is make two seperate Models, that do not extend from the same Model (out of necessity): Group1 and Group2. You would store the information that is common to both profiles in the UserProfile of the User object. Then in the UserProfile you would have a ForeignKey to both a Group1 and a Group2 object:
group1 = models.ForeignKey(Group1, blank=True, null=True)
You would have to do the logic checking yourself, to ensure that only one is ever valid (you could just do this in an overridden save() method or something), but then to grab all of a user's data at once, and also know which group they are on you could do the following:
User.objects.filter(username='blahblah').select_related('profile', 'profile__group1', 'profile__group2')
Only one query to the database would give you all the information you'd need about a user, and you'd also know which group they are in (the one that isn't 'None').
I hope that helps.
P.S. I am assuming in this that groups don't just have unique data to each other, but also unique functionality.

Categories