How i can get relative urls in my field after serialize? now i get abolute.
My model:
class Article(models.Model):
title = models.CharField(max_length=120)
image = models.ImageField()
text = models.TextField()
link = models.URLField()
And serializer:
class ArticleSerializer(ModelSerializer):
link = URLField()
class Meta:
model = Article
fields = '__all__'
Actually, without the http://... prefix, the url will not be a valid url. If you want to link somewhere inside your app, you can take the output of something like django's reverse and store it in a CharField (or just do some string manipulation by declaring a method, prior to inserting to the database or prior to serialization-deserialization).
Related
I'm building a blog website with Django, and for posts on the blog I want to have 2 pages, first page would be the page where all the posts are displayed as a list, and the second would be a page for a specific post, with all the details. On the first page I want to show every post with title, date, and a part of the post's text. I thought that I can add to the post model another field which'll hold a substring from the hole post's text. My post model is this:
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=500)
content = models.TextField()
display_content = models.TextField(blank=True)
tags = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
I want for every post the display_content field to hold the first 167 characters from the content field + "...", and I'm not sure that I'd have to implement something directly on the class Post, maybe a function, or if I need to make this operation on the view function that renders this page with posts.
You can define the logic in the __str__ method, but it might be better to define a utility function that you can later reuse:
def shorten(text, max_len=167):
if len(text) <= max_len:
return text
else:
return '{}…'.format(text[:max_len])
Note that an ellipsis character ('…') [wiki] is a single character, and normally not three inidividual dots.
Then we can use this in the __str__ method:
from django.conf import settings
class Post(models.Model):
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
title = models.CharField(max_length=500)
content = models.TextField()
display_content = models.TextField(blank=True)
tags = models.CharField(max_length=100)
date_posted = models.DateTimeField(auto_now_add=True)
def __str__(self):
return shorten(self.title)
For templates, Django already has a |truncatechars template filter. So if you plan to render this in a template, there is no need to implement this logic in the model. You can render the title then with:
{{ mypost.title|truncatechars:167 }}
This makes more sense, since a Django model should not be concerned with how to render data, a model deals with storing, and modifying data.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Note: Django's DateTimeField [Django-doc]
has a auto_now_add=… parameter [Django-doc]
to work with timestamps. This will automatically assign the current datetime
when creating the object, and mark it as non-editable (editable=False), such
that it does not appear in ModelForms by default.
I am working on a project where I want to create a slug for each post based on its title. Is it possible to generate a slug in such a way that it will be unique to the post, but will not change even if the title of the post is changed? I am using the model provided in the file 'model.py'. Can you provide guidance on how to accomplish this?
class Post(models.Model):
username = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
description = models.CharField(('Description'),max_length=250)
title = models.CharField(('Content Title'), max_length=250)
create_date = models.DateTimeField(default = timezone.now)
image_data = models.ImageField(upload_to='User_Posts', height_field=None, width_field=None, max_length=None)
slug = (title)
def __str__(self):
return self.title
I recommend checking out the Django documentation for slugify. You will need to override the save method of your model to do this, so your new code will most likely look something like this:
from django.utils.text import slugify
slug=models.SlugField()
def save(self,*args,**kwargs):
self.slug=slugify(self.title)
super(Post,self).save(*args,**kwargs)
I would keep in mind the unique parameter that you can set to either true or false in your slugfield.
I'm getting this error with TinyMCE in django:
TypeError: init() got an unexpected keyword argument 'widget'
I have followed the instructions as I found them, and don't know why the error is there. Here is the model:
class Article(models.Model):
"""Represents a wiki article"""
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=50, unique=True)
text = models.TextField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))# (help_text="Formatted using ReST")
author = models.ForeignKey(User)
is_published = models.BooleanField(default=False, verbose_name="Publish?")
created_on = models.DateTimeField(auto_now_add=True)
objects = models.Manager()
published = PublishedArticlesManager()
The comment "#formatted in ReST" is because the original TextField was using restructuredText. I was able to actually get tinyMCE from CDN and place a very simpel script in the head of the appropriate template. It loaded the wysiwyg editor, but then rendered the saved page with HTML tags visible.
So I added to form declaration as:
from django import forms
from models import Article, Edit, FileUploadHandler
from tinymce import models as tinymce_models
class ArticleForm(forms.ModelForm):
class Meta:
text = forms.Charfield(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))#(help_text="Formatted using ReST")
model = Article
exclude = ['author', 'slug']
class EditForm(forms.ModelForm):
class Meta:
model = Edit
fields = ['summary']
class UploadImageForm(forms.ModelForm):
class Meta:
model = FileUploadHandler
image = forms.ImageField()
fields = ['title']
The editor is there, but upon save its rendering the article with html tags visible. Why is that?
widget is an attribute for form fields, not model fields. You need to move that setting to your form declaration (or formfield_overrides if you're trying to use it in the admin).
To display the marked up content without escaping the HTML tags in a later view, one way is to use the |safe built in filter.
i have following models
class tags(models.Model):
tag = models.CharField(max_length=15) # Tag name
tagDescription = models.TextField() # Tag Description
tagSlug = models.TextField() # Extra info can be added to the existing tag using this field
class stores(models.Model):
storeName = models.CharField(max_length=15) # Store Name
storeDescription = models.TextField() # Store Description
storeURL = models.URLField() # Store URL
storePopularityNumber = models.IntegerField(max_length=1) # Store Popularity Number
storeImage = models.ImageField(upload_to=storeImageDir) # Store Image
storeSlug = models.TextField() # This is the text you see in the URL
createdAt = models.DateTimeField() # Time at which store is created
updatedAt = models.DateTimeField() # Time at which store is updated
storeTags = models.ManyToManyField(tags)
class tagsAdmin(admin.ModelAdmin):
list_display = ('tag', 'tagDescription', 'tagSlug')
class storesAdmin(admin.ModelAdmin):
list_display = ('storeName','storeDescription','storeURL',
'storePopularityNumber','storeImage',
'storeSlug','createdAt','createdAt','storeTags'
)
admin.site.register(tags,tagsAdmin)
admin.site.register(stores,storesAdmin)
Whenever I am trying to run command : python manage.py syncdb
I got the error: django.core.exceptions.ImproperlyConfigured: 'storesAdmin.list_display[8]', 'storeTags' is a ManyToManyField which is not supported.
I don't understand what I am doing wrong here. I want to simply display all the models in the django admin site.
You can't reference a Many2ManyField like that, you have to use a method instead in the stores class that looks like this
def get_tags():
return self.storeTags.all()
and reference that in your list_display(...'get_tags')
This is done because the M2M field would result in lots of SQL queries that would slow the entire thing down so therefore the choice would have to come from the developer and not from the framework.
Please check:
ModelAdmin.list_display
"ManyToManyField fields aren’t supported, because that would entail executing a separate SQL statement for each row in the table. If you want to do this nonetheless, give your model a custom method, and add that method’s name to list_display. (See below for more on custom methods in list_display.)"
You can use a custom method to show values of ManyToManyField or simply remove storeTags from list_display
Consider the following Django models:
class Host(models.Model):
# This is the hostname only
name = models.CharField(max_length=255)
class Url(models.Model):
# The complete url
url = models.CharField(max_length=255, db_index=True, unique=True)
# A foreign key identifying the host of this url
# (e.g. for http://www.example.com/index.html it will
# point to a record in Host containing 'www.example.com'
host = models.ForeignKey(Host, db_index=True)
I also have this form:
class UrlForm(forms.ModelForm):
class Meta:
model = Urls
The problem is the following: I want to compute the value of the host field automatically,
so I don't want it to appear on the HTML form displayed in the web page.
If I use 'exclude' to omit this field from the form, how can I then use the form to save information
in the database (which requires the host field to be present) ?
Use commit=False:
result = form.save(commit=False)
result.host = calculate_the_host_from(result)
result.save()
You can use exclude and then in the forms "clean" method set whatever you want.
So in your form:
class myform(models.ModelForm):
class Meta:
model=Urls
exclude= ("field_name")
def clean(self):
self.cleaned_data["field_name"] = "whatever"
return self.cleaned_data