By default, Django admin page basically form submitted data set to database naturally without any data edits.
However, I want to edit this.
When I develop blog to use Django admin, I have columns in table like this
| title | article_md | article_html
and I want to make article_html data not to edit directly in django admin page form but to generate html style data from markdown style data of article_md and to submit to database.
How can I do this? Is there any way to do something like generally controller in model.py or admin.py?
class Article(models.Model):
def __str__(self):
return str(self.title)
title = models.CharField(max_length=255)
article_md = models.TextField(null=True)
article_html = models.TextField(null=True)←I want it is generated by converting article_md's data
model.py
class Article(models.Model):
def __str__(self):
return str(self.title)
title = models.CharField(
max_length=255
)
article_md = models.TextField(
null=True
)
article_html = models.TextField(
null=True
)
def save(self, *args, **kwargs):
self.article_html = markdown.markdown(self.article_md, extensions=['gfm'])
super(Article, self).save(*args, **kwargs)
admin.py
class ArticleAdmin(admin.ModelAdmin):
exclude = ['article_html']
admin.site.register(Article, ArticleAdmin)
Related
I want to delete the data inside the file field and the file uploaded through the file field.
I'm beginner.
models.py
class Fruits(models.Model):
name = models.CharField(
_('Name'),
max_length=200,
)
description = models.TextField(
_('Description'),
null=True, blank=True,
)
this_is_my_file = models.FileField(
_('Photo image'),
null=True,
blank=True,
upload_to='myfile/'
)
def __str__(self):
return self.name
def delete(self, *args, **kwargs):
if self.this_is_my_file:
self.this_is_my_file.delete()
super().delete(*args, **kwargs)
Like the code above, I added 'def delete' to the existing model as shown above through search.
But I don't know how to use this function.
How do I use this in view and template?
My part of view is below.
views/fruits.py
class FruitsDetailView(LoginRequiredMixin, DetailView):
template_name = 'frutis/detail.html'
login_url = 'login'
model = MyObjects
def get_context_data(self, **kwargs):
pk = self.object.pk
context = super().get_context_data(**kwargs)
...
return context
How do I execute the delete function in this view?
I want to delete it when I press the 'delete' button on the template.
Should I send a post request from template and receive it from view?
I've been thinking about it for 4 days, but I don't know what to do.
I am using django-tables2 and trying to hide url and rename it on field. for example, url link is www.youtube.com but on actual field, I want it to show as 'link' instead of revealing entire url link. how do I achieve this?
tables.py
class MyVideoTable(tables.Table):
class Meta:
model = PPVideo
fields = ('title', 'url')
models.py
class PPVideo
title = models.CharField('Title', max_length=100, null=True)
url = models.URLField('URL', max_length=150, null=True)
You can define a .render_url(…) method to specify how to render this column:
from django.utils.html import format_html
class MyVideoTable(tables.Table):
def render_url(self, value, record):
return format_html('link', value)
class Meta:
model = PPVideo
fields = ('title', 'url')
I am learning django by building a simple blogging app. While its all but done, I currently have individual posts having a url in the format https://my_site_dot_com/blog/entry/38/ where the number 38 corresponds to the primary key of said post.
What i want is it to have the format https://my_site_dot_com/blog/entry/this_is_custom_title/ where "this_is_custom_title" corresponds to the heading of the post. I have no idea how to accomplish this. Can anyone offer any assistance?
My model looks like:
class Entry(models.Model):
entry_title = models.CharField(max_length=50)
entry_text = models.TextField()
image = models.FileField(upload_to="media", blank=True)
entry_date = models.DateTimeField(auto_now_add=True)
entry_author = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "blog"
def __str__(self):
return self.entry_title
I want the entry_title to the the custom url instead of the primary key.
My urls.py looks like this:
urlpatterns = [
path('', HomeView.as_view(), name="blog-home"),
path('entry/<int:pk>/', EntryView.as_view(), name="entry-detail"),
path('create_entry/', CreateEntryView.as_view(success_url='/'), name='create_entry'),
]
Edit:
The class handing the post looks like this:
class EntryView(DetailView):
model = Entry
template_name = 'blog/entry_detail.html'
data_set = random_info()
stuff_for_post = {
"info": data_set
}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['rand_im'] = random_image()
context['tags'] = ['tag1','tag2','tag3']
return context
I'm an absolute noob in django and come from android/java. So please give an easy to understand explanation.
Thanks in advance
You may add a slug field to your Entry model and a get_absolute_url method. Don't forget to import reverse function from Django's url module.
from django.urls import reverse
class Entry(models.Model):
entry_title = models.CharField(max_length=50)
entry_text = models.TextField()
image = models.FileField(upload_to="media", blank=True)
entry_date = models.DateTimeField(auto_now_add=True)
entry_author = models.ForeignKey(User, on_delete=models.CASCADE)
slug = models.SlugField()
def get_absolute_url(self):
return reverse('entry_detail', kwargs={'slug': self.slug})
class Meta:
verbose_name_plural = "blog"
def __str__(self):
return self.entry_title
Then, within the urls.py module of your app, add the following url pattern to the urlpatterns list. Don't forget to load the corresponding view, I guess it may be EntryView in this case.
from django.urls import path
from .views import EntryView
urlpatterns = [
...
path('<slug:slug>', EntryView.as_view(), name='entry_detail'), # new
...
]
Then the slug should replace the primary key pattern in the url.
To go a bit further, you can use a method within your model that slugify your title for instance. (define the method within the model then call it from the save method of the model, by overriding the save method)
https://docs.djangoproject.com/en/3.0/ref/utils/#django.utils.text.slugify
Currently you are passing an integer through your url. All you need to do is modify this slightly to pass a string through the url. Here is a similar question that discusses how to accomplish this.
As for changes you need to make in your code, urls.py will need to be updated
path('entry/<str:title>/', EntryView.as_view(), name="entry-detail")
You haven't provided your blog post view, but it will then look something like this:
def post(request, title):
template = "template.html"
post = Posts.objects.filter(entry_title==title)
return render(request, template, {'post':post})
If you are using a Class Based View you should use a slug.
First add a new field entry_slug to your Entry model and override the save method in order to automatically generate the entry_slug field:
class Entry(models.Model):
entry_title = models.CharField(max_length=50)
entry_slug = models.CharField(max_length=50)
...
def save(self, *args, **kwargs):
self.entry_slug = slugify(self.entry_title )
super(Entry, self).save(*args, **kwargs)
You can do by replacing the pk with entry_slug:
path('entry/<slug:entry_slug>/', EntryView.as_view(), name="entry-detail")
I'm making a hobby project with Django to store my ideas seperated by idea groups as the following:
class Idea(models.Model):
name = models.CharField(unique=True, max_length=50)
description = models.TextField()
in_process = models.BooleanField()
is_done = models.BooleanField()
group = models.ForeignKey(Group, on_delete=models.CASCADE, blank=False)
class Group(models.Model):
name = models.CharField(unique=True, max_length=25)
description = models.CharField(max_length=50, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=False)
Is there any way to restrict the currently logged in user from being able to see or modify ideas and idea groups created by other users using generic class based views?
class GroupDelete(LoginRequiredMixin, generic.DeleteView):
model = Group
pk_url_kwarg = "id"
success_url = reverse_lazy('ideas:list')
...and a url for example:
urlpatterns = [
path('<int:id>/delete', views.GroupDelete.as_view(), name='delete'),
]
I'm using Django 2.0.
I would suggest writing a custom mixin where you'd inherit the LoginRequiredMixin and then add your own logic verifying that the currently logged in user (which you can retreive from request.user) is the one who actually created the Group object.
Simple example would look something like this:
# mixins.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseNotFound, HttpResponseRedirect
class YourCustomMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs):
can_access = ... logic to check if user can access Group ...
disp = super().dispatch(request, *args, **kwargs)
if not isinstance(disp, HttpResponseRedirect) and not can_access:
return HttpResponseNotFound()
return disp
Once you have a value for the can_access flag, you call the LoginRequiredMixin's dispatch method and check if the result of that call is a redirect (to the login page) and check against the can_access flag, and then either return HttpResponseNotFound() or the original disp result.
Of course, you could also return HttpResponseForbidden() instead of HttpResponseNotFound().
You can then use it in your views, e.g.:
from your_app.mixins import YourCustomMixin
class GroupDelete(YourCustomMixin, generic.DeleteView):
...
In my django project i have a model.py with a class like this:
class temp_main(models.Model):
descr = models.CharField(max_length=200, verbose_name="Description")
notes = models.TextField(null=True, blank=True, verbose_name="Note")
dt = models.DateTimeField(auto_now=True)
#Fields for API permissions
owner = models.ForeignKey('auth.User', related_name='tmain_owner', on_delete=models.CASCADE, verbose_name="API Owner")
class Meta:
verbose_name = '1-Main Template'
verbose_name_plural = '1-Main Templates'
def __str__(self):
return self.descr
i would that in my admin panel the owner field was auto-populated with the current login user.
In my admin.py i write:
admin.site.register(temp_main, )
How can i set my owner field with logged in user?
Thanks in advance
I think what you need is the save_model method. Here's how it is used (from the documentation):
from django.contrib import admin
from myproject.myapp.models import Article
class ArticleAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user
super().save_model(request, obj, form, change)
admin.site.register(Article, ArticleAdmin)
I think you could change obj.user to obj.owner in your case. Does that work?
Also, I think you would want to change the name of the temp_main class to TempMain and then name the class in the admin.py file TempMainAdmin. Django will use this naming scheme to know which Admin Model goes with which model.