Django + DRF Create file from json value - django

I'm building a part of django+drf app that will create article models from the given JSON request. Example of request:
{
"title":"title"
"author":"author"
"text":"possible huge amount of text"
...
}
Article model:
class Article(models.Model):
title = models.CharField(max_length=config.ARTICLE_TITLE_MAX_LENGTH)
views = models.IntegerField(default=0)
author = models.ForeignKey(User, related_name='articles', on_delete=models.CASCADE)
date_created = models.DateTimeField('Date created', auto_now_add=True)
published = models.BooleanField(default=False)
text = models.FileField(upload_to='content/articles_storage/', null=True)
This data is processed by article serializer
class ArticleSerializer(serializers.ModelSerializer):
# content = serializers.CharField() ???
class Meta:
model = Article
# fields = ['id','title','views','date_created','content']
fields = ['id','title','views','date_created','text']
Serializer expects text field to be a file, however, it is gonna be plain text, so when the user makes a POST request to the server, I want the server to validate the text, create a file from this text, save it to the folder content/article_storage
When the user makes a GET request, I want the server to read that file and create a JSON response like above.
My question is what is the best way to do this? I definitely don't want to use django's TextField. Also I'm wondering if I actually need FieldFile, maybe it's better to store the text in a file with the name = article id?

Related

how to post data in django rest in a model that has Jsonfield

I have a task to create a simple post API to send a visitor messages through a contact form that contain fields like full_name,address,phone etc. But instead of creating a model, I have to use an already existing model which has a Jsonfield. Now what I need to do is to use that jsonfield which will have all the fields like name, address etc.
class Core(models.Model):
"""
Model that saves the corresponding credentials for the slug.
"""
slug = models.CharField(max_length=255, null=False)
example = models.JSONField(null=False, default=dict)
def __str__(self) -> str:
return self.slug
If it was done in a regular way by creating a model, it would have been like this.
class Contacts(models.Model):
full_name = models.CharField(max_length=100,blank=True,default="")
email = models.EmailField()
phone = models.CharField(max_length= 16)
address = models.CharField(max_length=255,blank=True,default="")
message = RichTextField()
def __str__(self):
return self.email
Now, how should I send these fields data in a dictionary without in that JsonField without creating a Contacts model?
First of all, this question is not clear. Please ask your question in a clearer way. I hope the way below helps you.
This field keeps data like;
{"full_name":"John Doe", "email": "johndoe#doe.com", "phone":"XXXXXXXXXXX"}
You may create dictionary and assign to field. Also you may create json data like this;
json_example = json.dumps(full_name="John Doe, email="johndoe#doe.com, phone="XXXXXXXXXXX")
and then create a Core object ;
core = Core(example = json_example)
core.save()

In Wagtail v2 API, how do I filter by a foreign key's string (provided by the __str__ method)

So I have a blog type of website where I'm trying to use the API to get a list of articles filtered by their topic. Here is the relevant portion of my ArticleDetailPage() class with the API field:
class ArticleDetailPage(Page):
"""Article detail page."""
...
topic = models.ForeignKey('articles.ArticleTopic', null=True, blank=True, on_delete=models.SET_NULL)
...
api_fields = [
...
APIField('topic', serializer=serializers.StringRelatedField(many=False)),
...
]
And here's my ArticleTopic() class:
#register_snippet
class ArticleTopic(models.Model):
"""
Article topics that resides in Snippets.
"""
name = models.CharField(max_length=100)
slug = AutoSlugField(
populate_from='name',
editable=True,
max_length=100,
verbose_name='slug',
allow_unicode=True,
help_text='A slug to identify articles by this topic.'
)
panels = [
FieldPanel('name'),
FieldPanel('slug')
]
class Meta:
verbose_name = 'Article Topic'
verbose_name_plural = 'Article Topics'
ordering = ['name'] # Alphabetial ordering
def __str__(self):
return self.name
So far so good, when I take a look at the API list of posts, instead of showing the topic attribute as its ID and other data, it's represented as its string representation (i.e. a topic like space or comets). However, when I try to filter the API by appending:
&topic=space
to the HTML, I get an error saying:
Field 'id' expected a number but got 'space'.
Instead of using the StringRelatedField(many=False) serializer, I switched to
APIField('topic', serializer=serializers.PrimaryKeyRelatedField(many=False, read_only=True))
So each topic is represented only as its ID and when I perform the same filtering above but using the ID instead of the string name, it works!
Ideally, I'd want to just filter using the string name instead of the ID for other purposes in my project. Anyone have any experience on this or would like to chime in?

Django: what is the better way to get users info from models in view or template?

I have few django models and I want display some information the for several users in the template.
Below are the models:
class CustomUser(AbstractUser):
def __str__(self):
return self.email
class Post(models.Model):
author = models.ForeignKey(CustomUser,on_delete=models.CASCADE,)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
post_url = models.URLField(max_length = 200, blank = True)
slug = models.SlugField(unique=True, blank=True)
class subscription(models.Model):
creator = models.ForeignKey(CustomUser,default=None, null=True,on_delete=models.CASCADE,related_name='creator',)
booster = models.ForeignKey(CustomUser,default=None, null=True,on_delete=models.CASCADE,related_name='booster')
sub_value = models.FloatField(blank = True)
sub_id = models.TextField(blank = True)
status = models.BooleanField(default=False)
dateSubscribed = models.DateTimeField(default=timezone.now)
dateSubscriptionEnded = models.DateTimeField(default=timezone.now)
paymentCount = models.FloatField(default= 0)
I want to pass few users to template and display how many posts and subscriptions each user has? I am wondering what is the best way to do it? Is better number of posts and subscribers information in the view and just pass those things to template or pass users get that information in the template? Thanks!
Model => View => Template
Try to parse as much of the information from the model in the view as possible. The reason for this is the pure python in the view runs fast and is nicer to work with the pure python. So when I can I try to break down information in the view into lists of objects. So for your example.
determine what users you want and add them to a list then loop through the list filtering using the username or id.
ex:
Post.objects.filter(author='User')
then create a list of objects with the relevant user, post count, and sub info.
then pass this to the template you can loop through the list using all the relevant data in your objects.
hope that was clear and useful some of that is my own development bias there may be a better way but that's how I have approached a similar issue in the past. good luck!

Django models in file sharing system

models.py :
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
user = models.ForeignKey(User, null=False, blank= False)
I have created a model for file upload as shown above. docfile is the field that represents file to be uploaded and user field stores the name of the user that is uploading the file.I want the additional fields so that file uploaded is visible to the ones with whom it has been shared. Tell me the fields for achieving the sharing task.
You would another field which has a foreign key to Django User Model.
user = models.ForeignKey(User, null=False, blank= False)
then whenever you want to fetch documents based on the logged in user, you would use this
docs = Document.objects.filter(user=request.user)
In models.py
users = model.ManyToMany(User)
this should work, although am not so sure. But feel free to let me know if you by chance run into any problem
In views.py
docs = Document.users.filter(username=request.user.username)

Relationships with Django and rest framework add replace fields

My user object with rest framework has an avatar_id and a cover_id. But Instead of displaying that to the API, I want it to be the actual avatar URL and cover URL already.
My User model:
avatar_id = models.IntegerField()
cover_id = models.IntegerField()
My UserAvatar model:
id = models.IntegerField(primary_key=True)
user_id = models.IntegerField()
file_id = models.IntegerField()
My Files model:
id = models.IntegerField(primary_key=True)
filename = models.CharField(max_length=255)
Same concept with UserCover.
How do I remove the avatar_id from the results of /users/ and add a avatar field with the actual avatar filename?
I'm not sure I understand your question correctly, but here what I think the problems are. Reading your question, I assumed that you are a beginner, so I answered as such. Sorry if it's not the case.
You don't need to add the id fields, it's done automatically by Django because all tables need a primary key. You define a PK only when you need to name it something else than 'id'.
You should really read the Django tutorial which explains how to define models. User.cover_id and UserAvatar.file_id should be defined as ForeignKey. If you don't know what a foreign key is, then stop playing with Django and read a database tutorial before.
There's already a model and a set of classes to manage your users in Django. You should use them. For example, a "user profile" is the right way to extend the user model.
If you force the users to choose one avatar in a set of predefined avatars, then what you want to do is ok. If the users can choose any avatar (upload), then you should use OneToOneField or put it directly in the user model (or profile).
I don't know what is a UserCover, but here's what your models could look like:
from django.contrib.auth.models import User
class UserProfile(models.Model):
# Link to Django normal User (name, email, pass)
user = models.ForeignKey(User, unique=True)
# Any information that a user needs, like cover, wathever that is, age, sexe, etc.
avatar = models.CharField(max_length=255)
Or like this if a will be reused often :
class Avatar(models.Model):
# name = ...
# description = ...
path = models.CharField(max_length=255)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
avatar = models.ForeignKey(Avatar, unique=True)
# other data