Working with accounts and user generated data in Django - django

I haven't found any documentation or tutorials on this topic, haven't received any answers on the IRC channel either so it makes me think I'm looking for the wrong thing. Anyway, resorting to SO after several hours of searching. I'll try to describe what I'm after by example:
I want to create a web application where user could create an account (this part is rather clear
After logging in, user would be able to store his favorite meals
When a user is logged in, he would see a list of his favorite meals and he could edit them
I understand how user can create account and log in. But everything after that is kind of blurry.
After user logs in, let's say he would be presented with a form he could fill in and save. How should the database (models) be designed to handle this? Would each user get his own table? How to retrieve the user stored data (i.e. favorite foods) from the database?
These are the things I'm trying to figure out while learning django/programming in general. As I said I haven't found it described in any books, docs or tutorials I went through.
I would appreciate if you could point me to the right direction. I feel like I'm missing something here.

Basic stuff:
make a foreign key for the user in your model
suppress the user field from the form
save the form with commit=False, set the user to the authenticated user and save the model.
The rest you can get pretty straight forward from the tutorial.
For example:
# At models.py
from django.contrib.auth.models import User
class FavoriteMeal(models.Model):
user = models.ForeignKey(User)
# other fields...
# At forms.py
class FavoriteMealForm(forms.ModelForm):
class Meta:
model = FavoriteMeal
exclude = ('user', )
# At views.py
#login_required
def favorite_meals_view(request):
favorite_meals = FavoriteMeal.objects.filter(user=request.user)
...
if request.method == 'POST':
form = FavoriteMealForm(request.POST)
if form.is_valid():
favorite_meal = form.save(commit=False)
favorite_meal.user = request.user
favorite_meal.save()
...

What you are looking is for is really very basic part of django. I would suggest you to go through tutorial. This would give you a fair amount of idea of how the model relationship could be used to store the data.
https://docs.djangoproject.com/en/1.4/intro/tutorial01/

Related

How to save user query terms from a search navbar in database that can be acessed after user sessions?

I have a search navbar and I want to save search queries so I can improve the navbar and the autocomplete api, but I'm not sure how. sessions variables seem to only work when user is online and it's difficult to save many users. Should I create my own user model and then write data to it. Can you give me a simple example of how to do this?
I've tried using sessions.request to save variables and then access them after a session and have been unable.
You question is a bit unclear but why not create a table for search terms and foreign key to user model if that's what you need. For example:
class SearchTerm(models.Model):
keywords = models.TextField()
user = models.ForeignKey(User)
Naturally, this will work for logged in users only where you can do something like this in your view:
def search(request):
keywords = request.get('keywords')
user = request.user
st, created = SearchTerm.objects.get_or_create(keywords=keywords, user=user)
Look, this is a very simplistic example to illustrate what I think you want to do, but I'm not sure if I have fully understood your question.

Django Authentication - Filter only user-created (not all) records in View

I am using Python 3.6 and Django 1.11
I have a working app (for learning purposes) that authenticates users, then allows the user to create "things" in a Django form, based on a model. In this case, users can "quit" something, like smoking or drinking, and specify their Quit Date, etc. The home page currently displays a list of all "things" created by ALL users. Anybody in the world can view these.
What I'd like to do is limit this View so that 1) only authenticated users can view 'things' from the database, and 2) authenticated users can view ONLY their "things".
How I imagine this would be accomplished is starting in the app/views.py file. Cuurently, the home page view (a list of all things) looks like this:
def something_list(request):
things = Thing.objects.filter(quit_date__lte=timezone.now()).order_by('quit_date')
return render(request, 'quit/something_list.html', {'things': things})
This defines a View which orders by 'quit date', and sends it to my 'something list' template.
By searching online, it seems possible to specify only seeing the user's data by adding a parameter to the Thing.objects.filter(). Everything I have tried thus far is causing errors, including this:
things = Thing.objects.filter(owner=request.user).filter(...)
and this
things = Thing.objects.filter(owner=request.user, quit_date__lte=timezone.now()).order_by('quit_date')
Here is my model, just so you know the field names:
class Thing(models.Model):
quitter = models.ForeignKey('auth.User')
title = models.CharField(max_length=200)
quit_date = models.DateTimeField(default=timezone.now)
cost_per_day = models.DecimalField(max_digits=6, decimal_places=2)
notes = models.TextField()
Once again, I'm trying to figure out how to modify my view (above) so that authenticated users see ONLY the 'things' that they have created. Also, I want unauthorized users to see NONE of the 'things'. Hopefully, both can be accomplished with the same line of code.
Thanks in advance. I'm a beginner. Please let me know if more info is needed for an answer.
UPDATE: (solution)
The solutions offered by others below are correct. Here is the line of code that works for me:
things = Thing.objects.filter(quitter=request.user).filter(quit_date__lte=timezone.now()).order_by('quit_date')
When I made this change, I got an 'AnonymousUser' object error. I needed to sort out my default view for unauthenticated users. If a user is logged in, they now see only their data, but if an anonymous user views this page, they got an error. I added an "if, else" conditional to my view to handle this. It now seems to be working and I thought I'd share my entire view, in case it might help someone.
def something_list(request):
if request.user.is_authenticated:
things = Thing.objects.filter(quitter=request.user).filter(quit_date__lte=timezone.now()).order_by('quit_date')
return render(request, 'quit/something_list.html', {'things': things})
else:
return render(request, 'quit/base.html')
Your field is called quitter, not owner.
Thing.objects.filter(quitter=request.user, ....)
For future reference, when you get errors, you should post them in the question.

With django, how can I retrieve if the user "likes" the article of other items?

I have 3 tables in my database, the first one is the "user" table with users' basic information, the second one is the "article" table, and the last one is the "user_like_article" table which store a record for a user and a article if the user likes the article.
For instance, if a user A like an article X, the the record in the "user_like_article" table will be like this: (A,X)
So now, I want to indicate whether the user, who has logged in, like a certain article in the article list I diplay.
I have figure out a way. I first get the article list. After that, I get the list of article's id which the specific user likes. The other things work like the code below
for article in articles_to_diplay:
if article in article_list_user_likes:
article['like'] = True
This method works, but somehow I think it is too expensive. Displaying "like" button is just a little part of my project, but it is indeed very common. Facebook, Twitter, blogs, "like" is in widespread use.
Is there any way less expensive to accomplish this feature?
Thank you very much!
It's not quite simple to use some nice looking API, since we check query against logged in user object, so we need to inject is_liked method for each article object.
Also you can use ManyToManyField field for Article model, instead creating additional table (unless you're using some extra data, then let me know, so I can modify the answer accordingly.
models.py
from django.contrib.auth.models import User
class Article(models.Model):
title = models.CharField(max_length=50)
likes = models.ManyToManyField(User)
def __unicode__(self):
return self.title
views.py
def home(request):
articles = Article.objects.all().prefetch_related('likes')
for a in articles:
a.is_liked = (request.user in a.likes.all())
return render(request, 'home.html', {'articles': articles})

MongoEngine query to get Post's author and Comments authors for Posts (at the same time)

I'm working on a web project with Django and MongoDB as my database (using MongoEngine to connect them).
I have to create Celery task to cleanup old user accounts. I need to only clean lazy users accounts without any content after one month (lazy users are automatically created users when they first connect to the website). What count as content? Any posts from the user or comments on any of the posts.
I did it like this, but I want to transform this into query if possible:
def clean_inactive_lazy_users():
users_with_content = []
for post in api_models.Post.objects:
users_with_content.append(post.author)
for comment in post.comments:
users_with_content.append(comment.author)
users_with_content = list(set(users_with_content))
for user in account_models.User.objects:
if not user.is_authenticated() and (timezone.now() - user.connection_last_unsubscribe).days >= settings.DELETE_LAZY_USER_AFTER_DAYS and user not in users_with_content:
user.delete()
The models look like this:
base.py
class AuthoredEmbeddedDocument(mongoengine.EmbeddedDocument):
author = mongoengine.ReferenceField(models.User, required=True)
class AuthoredDocument(mongoengine.Document):
author = mongoengine.ReferenceField(models.User, required=True)
api_models:
from . import base
class Comment(base.AuthoredEmbeddedDocument):
"""
This class defines document type for comments on posts.
"""
class Post(base.AuthoredDocument):
"""
This class defines document type for posts.
"""
account_models:
class User(auth.User):
def is_authenticated(self):
return self.has_usable_password()
Hopefully I provided enough information so you can help me with the problem. Thanks!
I think there are a couple ways for you to clean this up.
You could get all author unique ids of posts with something like:
user_ids_with_posts_list = Posts.objects.scalar('author.id', flat=True).distinct('author.id')
scalar should give you a list of author ids instead of document objects and distinct
should make sure they are unique. This pushes what you are doing in python to mongodb
You could then construct a query for Users. You would hvae to change your days ago into a date. What condition is has_usable_password checking for?
start_time = timezone.now() - timedelta(days=DAYS_AGO_CONSTANT)
invalid_users = User.objects.filter(connection_last_unsubscribe__lte=start_time,
password__isnull=True).exclude(pk__in=user_ids_with_posts_list)
invalid_users.delete()

Django Forms and Buttons

I have been working on forms only recently and I am still puzzeld by them.
What I want are standard Forms:
Next Button
Submit Data to Db
Timestamp
Clickable Images with Regions defined where when I click I get to the next page
And
I would like to combine these.
E.g. have a next button + Record the Timestamp.
or
E.g. Click into an Image + Next + Timestamp
If anybody could give me some examples for code that can achieve that or a good online resource on where to get info on that, that would be awesome.
Thanks for the time!!
I'm a little unclear about what you're trying to accomplish, but if you're trying to move data from an HTML form to the database, I'd suggest looking at how to use ModelForms. In a nutshell, you create a model class, like this:
class MyModel(models.Model):
field1 = models.CharField(max_length=50)
Then you create a ModelForm class that references that model:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
You can render an instance of MyModelForm in a view function. Inside of a POST request in that view, you bind the POST data to the form, validate it, and call save() on it to commit it to the database:
if request.method == 'POST':
form = MyModelForm(request.POST)
if form.is_valid():
model_instance = form.save()
This really isn't a question, I'm not exactly sure what you're trying to accomplish.
If you want to use Django forms, start here, or here.
I assume the stuff you mention about a timestamp should probably be an auto_now field in a model. Take a look at this.
The stuff you mention about buttons and click-able images is really just HTML and has nothing to do with Django. I would try Google for that.