How to allow user to edit post with Django? - python

In my blog I decided to allow users to edit posts (I am using Django), but I am not sure what is the right implementation for my models to do that. Is a good idea to use multi-table inheritance as my code below? I also want to keep track of all the posts, originals as the every new edited as well.
class Post(models.Model):
title = models.CharField(max_length=500)
text = models.TextField()
creation_date = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User)
def __unicode__(self):
return "%s %s by %s" % (self.title, self.creation_date, self.user)
class Edit(Post):
edited_date = models.DateTimeField(auto_now_add=True)
editor = models.OneToOneField(User)
def __unicode__(self):
return "%s edited by %s" % (self.convention, self.login)

What you need is version control. There are apps that can implement it. But if you want to do it yourself, then your Edit model must have a reference to the Post models. And must point to a specific post corresponding to the author of that edit. That necessarily means you have to create a Post instance every time a post is saved and you must point to that new instance from the Edit instance.
Something like this, but may need more work -
class Post(models.Model):
title = models.CharField(max_length=500)
text = models.TextField()
creation_date = models.DateTimeField(auto_now_add=True)
edited_date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User)
def __unicode__(self):
return "%s at %s by %s" % (self.title, self.creation_date, self.author.first_name)
class Edit(models.Model):
creation_date = models.DateTimeField(auto_now_add=True)
editor = models.ForeignKey(User)
post = models.ForeignKey(Post)
def __unicode__(self):
return "%s edited by %s" % (self.post.title, self.editor.first_name)

Related

Changing default value of cell using DJango and SQlite3

I have a problem, I am doing project in Django for my University, and I don't know how can I change value of cell in Database using views.py. My application is an application to do exams online and problem is that many users need to use it at the same time, so I need to do relations in database, like every question has an answer and that answer is provided by one user. And there is problem, I don't know how can I change this dynamically in Views.py.
This is my code from Views.py:
if form.is_valid():
if username == Users.objects.latest('name'):
Choice.objects.username = Users.objects.get('name')
And my models.py:
class Answers(models.Model):
question = models.ForeignKey(Questions, on_delete=models.CASCADE)
text = models.TextField()
def __str__(self):
return self.text
class Users(models.Model):
name = models.CharField(max_length=30)
pass = models.CharField(max_length=30)
def __str__(self):
return self.name
class Choice(models.Model):
username = models.ForeignKey(Users, null=True, on_delete=models.CASCADE)
question = models.ForeignKey(Questions, null=True, on_delete=models.CASCADE)
answer = models.CharField(null=True,max_length=50)
class Questions(models.Model):
text = models.CharField(max_length=150)
madeBy = models.ForeignKey(User, null=True, blank=False, default='kacper', on_delete=models.CASCADE)
def __str__(self):
return self.text
Also if you have any other idea how could I improve this would be great, it's first time that I'm doing something in DJango.
If I understand your question correctly you want to update("how can I change value of cell ...") an specific object. To do this you can use following command :
YourModel.objects.filter(pk=yourobject_pk).update(username=Users.objects.get('name'))
Have this in mind, first you have to filter the object you want to update(I suggest doing this by id) and then update the field(cell) you want.

Django: Can't query a foreign field

I'm still a novice so any help is gladly appreciated. Running Django 1.10
I'm trying to retrieve all the profiles that are assigned a particular manager but my query set always comes up empty.
Model.py
Blockquote
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=30, blank=False)
last_name = models.CharField(max_length=30, blank=False)
email = models.EmailField( blank=True, help_text='Optional',)
receive_email_notifications = models.BooleanField(default=False)
manager = models.ForeignKey(User, unique=False, blank=True, related_name='+', null=True)
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def publish(self):
return self.save
def __str__(self):
return str(self.user)
View.py
Blockquote
def instrument_list(request):
# pulls all instruments from instrument model
instruments = Instrument.objects.all().order_by('instrument_name')
test = Profile.objects.filter(manager='jenn')
print(test)
# pulls all checklists from checklist model
checklists = Checklist.objects.all().order_by('created_date')
# takes instruments, pushes them to template with variable 'instruments'
return render(request, 'blog/instrument_list.html', {'instruments': instruments, 'checklists': checklists})
I've also tried filtering a single profile entry (with a non-foreign key attribute) and printing how managers are saved in the database and the output looked like this
Blockquote
<User: jenn>
However, even when I try filtering with that output, my query sets come up empty
Blockquote
test = Profile.objects.filter(manager='<User: jenn>')
I think I need to adjust my filter parameter to something the database can match against but I'm not sure what that format is. I've tried looking through the documentation but haven't found exactly what I'm looking for.
But that's just a string representation of a model instance. You need the actual instance.
jenn = User.objects.get(username="Jenn")
test = Profile.objects.filter(manager=jenn)
Of course, once you already have jenn as an instance, to can use the reverse accessor of the fk instead:
test = jenn.profile_set.all()
And if you don't have jenn, and you don't need it, you can do the whole thing in one query:
test = Profile.objects.filter(manager__username="Jenn")
I've also tried filtering a single profile entry (with a non-foreign key attribute) and printing how managers are saved in the database and the output looked like this
That's not how managers are saved in databases, thats just a "readable" representation of an instance user.
If you want to filter on a manager you can do something like that :
test = Profile.objects.filter(manager__pk= primary_key_of_manager)
or
temp_manager = User.objects.get(...)
test = Profile.objects.filter(manager=temp_manager)

Django model references from a different model

I'm writing a method in a model and I need to access an attribute from another model.
from django.db import models
class Image(models.Model):
name = models.CharField(max_length=30)
image = models.ImageField(upload_to = slug_path)
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
def slug_path(self):
# Need Article.slug from Article class here for constructing path
pass
class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
slug = models.SlugField(max_length=50)
def __str__(self):
return self.headline
I want to write a method in the Image class that will have access to the slug of the Article it is included in via the one to many relation. Is this possible or is there a different way I should be going about this entirely?
Say if only one image can be related to one article, you need to add a field article in the image model which would be foreign key to Article model
article = models.ForeignKey(Article)
Now,
def slug_path(self):
slug = self.article.slug
return slug
Anyway, you can do it in a similar way for many to many fields etc.
Add a relationship to Image corresponding to the Article object, like you did with Article and Reporter.
article = models.ForeignKey(Article, on_delete=models.CASCADE)
Then to get/return the slug:
def slug_path(self):
return self.article.slug

Adding a computed default value to Django model, how?

I'm trying to learn Python and Django by implementing an online forum. Right now, I'm trying to set the default value of the post title to "Re:" + thread.title, but I can't seem to do it.
I've searched for anything like this but nothing seems to answer my problem.
Here's my code (models.py):
from django.db import models
class Thread(models.Model):
title = models.CharField(max_length=50)
def __unicode__(self):
return u'[id=%s]%s' % (self.id, self.title)
class Post(models.Model):
thread = models.ForeignKey(Thread)
title = models.CharField(max_length=50)
post_date = models.DateTimeField(auto_now_add=True)
content = models.TextField()
def __init__(self):
super(Post, self).__init__()
if not self.title:
self.title = "Re: %s" % self.thread.title
def __unicode__(self):
return u'%s::[id=%s]%s' % (self.thread, self.id, self.title)
I hope someone can help me.
Regards,
Chad
You probably want to set the default value in the overridden save method. Your __init__ code doesn't work because at that point self.thread is not set yet.

What is the proper way to structure models.py?

I'm trying to build the right models for my Django app. I'm trying to build something that will allow a user to save a URL into one (or more) playlist(s) that is tied to that user. Before I implement this, I want to make sure that this is the best way to structure my models.py.
class UserProfile(models.Model):
user = models.ForeignKey(User, primary_key=True) #what is the difference between ForeignKey and OneToOne? Which one should I use?
Playlist = models.CharField('Playlist', max_length = 2000) #1 user should be able to have multiple playlists and the default playlist should be "Favorites"
def __unicode__(self):
return self.User
class Videos(models.Model):
Video_url = models.URLField('Link to video', max_length = 200, null=True, blank=True)
Playlist = models.ManyToManyField(Playlist) #this should connect to the playlists a user has. A user should be able to save any video to any plalist, so perhaps this should be ManyToMany?
def __unicode__(self):
return self.Video_url
Woah. Firstly the question is probably too "localised" for SO. Anyway. I'd do it like this:
class PlayList(models.Model):
playlist = models.CharField(max_length=2000)
class UserProfile(models.Model):
# do you want each `User` to only have one `UserProfile`? If so then OneToOne
# primary keys are automatically formed by django
# how django handles profiles: https://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
user = models.ForeignKey(User)
def __unicode__(self):
return self.User
class UserPlayList(models.Model):
# don't capitalise attributes, if you haven't seen PEP8 before, do now: http://www.python.org/dev/peps/pep-0008/
profile = models.ForeignKey(User)
playlist = models.ForeignKey(PlayList)
class Video(models.Model):
video_url = models.URLField(max_length=200, null=True, blank=True, help_text="Link to video")
def __unicode__(self):
return self.video_url
class VideoPlayList(models.Model):
video = models.ForeignKey(Video)
play_list = models.ForeignKey(UserPlayList)

Categories