Following code snippet I have tried but did not work for me
class User(AbstractBaseUser):
class Meta:
app_label = 'apis'
That seems to be misplaced - app_label is placed with a Django app in the urls.py file to namespace the templates within the app.
If you have an app called users with a users/models.py file containing:
class User(AbstractBaseUser):
...
Then you could make a sibling file for your user routes called users/urls.py, and include:
from django.urls import path
from .views ListUserView
app_name = "users"
urlpatterns = [
path("list/", ListUserView.as_view(), name="list"),
]
Then you could access this route in your templates by using {% url 'users:list' %}, for example. Good luck!
Related
I'm using REST in Django, And I couldn't understand what is the main difference between classic URL and instantiating DefaultRouter() for registering URL by ViewSet.
I have a model:
class Article(models.Model):
title = models.CharField()
body = models.TextField()
author = models.ForeignKey()
Serializing model like this:
from blog.models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['title', 'body', 'author']
View Class:
from blog.models import Article
from rest_framework import viewsets
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
serializer_class = ArticleSerializer
queryset = Article.objects.all()
and URLS:
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Is it possible to use classic URL in URLS.py instead of instantiating the object for a ViewSet like this:
urlpatterns = [
path('api/', 'views.someAPI'),
]
I just know HTTP method in ViewSet translate methods to retrieve, list and etc...
The Question is can we use traditional(Classic) URL style in this situation, Should we ?
Thanks for your help.
Well, in a nutshell as a django developer it is notorious how it is hard to deal with normal urls in django in some cases. Every now and again we get confused with the id type of the detail page that in some case are strings or integers with its regex, and so on.
For example:
urlpatterns = [
url(r'^(?P<content_type_name>[a-zA-z-_]+)$', views.content_type, name = 'content_type'),
]
# or
urlpatterns = [
url(r'^(?P<content_type_name>comics|articles|videos)$', views.content_type, name='content_type'),
]
Not mentioning that in almost every case its needed to have two urls like:
URL pattern: ^users/$ Name: 'user-list'
URL pattern: ^users/{pk}/$ Name: 'user-detail'
THE MAIN DIFFERENCE
However, using DRF routers the example above is done automatically:
# using routers -- myapp/urls.py
router.register(r"store", StoreViewSet, basename="store")
How django will understand it:
^store/$ [name='store-list']
^store\.(?P<format>[a-z0-9]+)/?$ [name='store-list']
^store/(?P<pk>[^/.]+)/$ [name='store-detail']
^store/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='store-detail']
See how much job and headache you have saved with a line of code only?
To contrast, according to DRF documentation the routers is a type of standard to make it easy to declare urls. A pattern brought from ruby-on-rails.
Here is what the documentation details:
Resource routing allows you to quickly declare all of the common
routes for a given resourceful controller. Instead of declaring
separate routes for your index... a resourceful route declares them in
a single line of code.
— Ruby on Rails Documentation
Django rest framework documentation:
Some Web frameworks such as Rails provide functionality for
automatically determining how the URLs for an application should be
mapped to the logic that deals with handling incoming requests.
REST framework adds support for automatic URL routing to Django, and
provides you with a simple, quick and consistent way of wiring your
view logic to a set of URLs.
For more details follow the django rest framework documentation.
while practicing on Django I have faced the following problem of Identical URL Pattern. I have tried but fail to solve.
My project has one apps and the models are
class Category(models.Model):
title = models.CharField(max_length=150)
slug = models.SlugField(unique=True,blank=True, max_length=255)
class Post(models.Model):
title = models.CharField(max_length=200)
cats = models.ForeignKey(Category, on_delete=models.CASCADE)
slug = models.SlugField(unique=True,blank=True, max_length=255)
My urls.py
from django.contrib import admin
from django.urls import path
from post import views as apps
urlpatterns = [
path('admin/', admin.site.urls),
path('<slug:slug>/', apps.categoryView, name='category'),
path('<slug:slug>/',apps.PostView, name='calc_detail'),
]
Problem:
When I Put '/' in the second line of the urlpattern for Category View, category View works but post View doesn't work (404).
If remove '/' urlpattern for CategoryView , then post view Works but Category Views shows 404.
How should I configure these urls. I am using function based views
There's really no way to handle these except using different patterns or handling both in the same view, I would suggest different patterns:
from django.contrib import admin
from django.urls import path
from post import views as apps
urlpatterns = [
path('admin/', admin.site.urls),
path('pattern1/<slug:slug>/', apps.categoryView, name='category'),
path('pattern2/<slug:slug>/',apps.PostView, name='calc_detail'),
]
Also have you thought what would happen if a post and a category ended up having the same slug? Best to have different patterns.
About putting '/' making some url work and not it is because django appends slashes by default to each url, so if you really want to do this (NOT RECOMMENDED) you may set APPEND_SLASH = False in your setting and have one url with a slash and other without.
I am new to Django and would greatly appreciate your help.
I have the below mentioned piece of code from an older book about Django. However, django.views.generic.list_detail has been deprecated. Can someone tell me how I could re-write this code with django.views.generic.list.ListView?
from django.conf.urls import patterns, include, url
from cmsproject.cms.models import Story
info_dict = {'queryset': Story.objects.all(), 'template_object_name': 'story'}
urlpatterns = patterns('django.views.generic.list_detail',
url(r'^(?P<slug>[-\w]+)/$', 'object_detail', info_dict, name="cms-story"),
url(r'^$', 'object_list', info_dict, name="cms-home"),
)
Assuming all you want to do is fetch a list of Story model objects, this is one way to write your views.py and urls.py:
In views.py:
from django.views.generic.list import ListView, DetailView
from cmsproject.cms.models import Story
class StoryListView(ListView):
model = Story
template_name = "cms/story_list.html"
class StoryDetailView(DetailView):
model = Story
template_name = "cms/story_detail.html"
template_name depends on where in the project you placed your html files. By setting model = Story, ListView will fetch Story.objects.all(). To customize, filter, add context etc., you can override any of the methods that your class based view inherits from its parent view (ex. in StoryListView you can override ListView methods).
In urls.py
from django.conf.urls import patterns, url
from cmsproject.cms.views import StoryDetailView, StoryListView
urlpatterns = patterns('',
url(r'^(?P<slug>[-\w]+)/$', StoryDetailView.as_view(), name="cms-story"),
url(r'^$', StoryListView.as_view(), name="cms-home"),
)
Think of urls.py as a mapping between the url and the View object. Defining name allows you to refer/link to other views by including name as a parameter to url template tag in the templates.
Some Extremely Useful References:
Effective Django - Class Based Views
CCBV List View
Django Project Generic Display Views
Built-in template Tags and filters -> look under url
I have a portfolio page with django, and i'm noticing a strange behaviour when a try to save an edited entry. It saves, and then it seems that the redirect fails to catch the ID and then goes to a 404 page that says domain.com/admi/internal_error.html/ in the URL (note the admi, sometimes is ad or adm). It happens with both 'Save' and 'Save and continue editing'.
This is my model
from django.db import models
from ramonlapenta.portfolio.managers import EntryManager
from ramonlapenta.slughifi import slughifi
class Type(models.Model):
type = models.CharField(max_length=100)
def __unicode__(self):
return self.type
class Entry(models.Model):
type = models.ForeignKey(Type)
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100)
slug = models.SlugField()
description = models.TextField()
requirement = models.TextField()
solution = models.TextField()
url = models.CharField(blank=True, max_length=64)
published = models.BooleanField(db_index=True, default=True)
logo = models.ImageField(upload_to="logos")
image = models.ImageField(upload_to="portfolio", height_field='height', width_field='width')
height = models.CharField(max_length=3)
width = models.CharField(max_length=3)
objects = EntryManager()
def __unicode__(self):
return u"%s - %s" % (self.title, self.created)
class Meta:
verbose_name_plural = "entries"
def save(self, *args, **kwargs):
self.slug = slughifi(self.title)
super(Entry, self).save(*args, **kwargs)
And this is the admin.py
from django.contrib import admin
from ramonlapenta.portfolio.models import Type
from ramonlapenta.portfolio.models import Entry
from django import forms
class EntryAdmin(admin.ModelAdmin):
fieldsets = [
('Title', {'fields' : ['title']}),
('Address', {'fields' : ['url']}),
('Description', {'fields' : ['description','requirement','solution']}),
('Type', {'fields' : ['type']}),
('Image', {'fields' : ['logo', 'image']}),
]
list_display = ('title', 'created')
list_filter = ['created', 'type']
admin.site.register(Type)
admin.site.register(Entry, EntryAdmin)
This is my entry manager, where i only filter the results.
from django.db import models
class EntryManager(models.Manager):
def published(self):
return self.model.objects.filter(published=True).order_by('-id')
This is the general urls.py
from django.conf.urls.defaults import patterns, include, url
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^', include('site.pages.urls')),
(r'^', include('site.blog.urls')),
(r'^', include('site.portfolio.urls')),
(r'^admin/', include(admin.site.urls)),
)
And the portfolio urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('ramonlapenta.portfolio.views',
url(r'^portfolio/$', 'index', name="port-main"),
url(r'^portfolio/(?P<item_slug>[a-zA-Z0-9_.-]+)/$', 'detail', name="port-slug"),
url(r'^portfolio/type/(?P<type>[a-zA-Z0-9_.-]+)/$', 'type', name="port-type")
)
Thos is what i see with HttpFox:
Note: everything else works fine, even there it sometimes works fine, and the public site works fine too. The problem is just editing a portfolio entry.
Does anybody knows why is this happening and how can i fix it?
My guess is that the main url.py is catching some of the admin data (being that any admin action will be considered by all the other urlconfs.
Try to put the admin urls at the top:
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^', include('site.pages.urls')),
(r'^', include('site.blog.urls')),
(r'^', include('site.portfolio.urls')),
)
Edit: second guess
The key information is that second 302 in the request list. Someone (probably dreamost's apache) is eating the response and returning a redirect to a custom page.
In this case setting DEBUG = True is of no help, because the response would have anyway the same error.
This means two things:
You have an error somewhere in your Model's code, probably some attribute/field/property that's used to display the object.
To isolate the error, try to find a pattern on which specific values trigger the error and which values allows to load the admin form.
You can't see the django error page unless you either work locally in the development server (manage.py runserver) or disable custom error pages in dreamhost as other suggest.
Knowing your setup and what appears in server logs at the time you're saving an entry might help us locate a problem. It's likely that the cause is outside Django (since the bug is not reproducible under Django's development server).
Anyway, you might find some of these solutions relevant:
Django on dreamhost problem (old post, but symptoms described there are similar, might be relevant if you're running Django on FastCGI).
getting 500 internal server error with django on dreamhost (in short: just try re-create the whole setup and see if that helps).
Or you may want simply to google dreamhost django 500 in case you haven't already, seems like people frequently encounter similar problem while setting up Django on Dreamhost.
I'll be curious to see your urls.py . My guess is that the regex for the admin site is bogus.
For sure an error is happening when you save those entries and you should check your logs. Or try reproduce it with DEBUG=True
My guess is that you are using dreamhost and Dreamhost allows you to define custom error pages and "internal_error.html" is for the status 500 error page (see : http://wiki.dreamhost.com/Creating_custom_error_pages).
Try to have a look at your dreamhost error.log file.
The sure thing is that the problem comes from your dreamhost configuration and not your django code (since it is working properly in development with Django 1.2)
all! I am writing a Django blog site.
I am new to Django. Since Django has the philosophy of loose coupling, I believe it's best to follow their beliefs when using their framework.
So I am encountering a dilemma here:
I want to set up some variables for my blog, say, the blog title, slogan, and the maximum length of digest on the homepage of each blog I wrote, and how many blog digest should I display on the homepage per page.
I can do this by creating a new app in my Django project, and create models for my site's config variables, then read those variables from other app, but this practice obviously breaks the philosophy of loose coupling.
The only work around I can think of is setting up environment variables in my sites .wsgi file (I use Apache and mod_wsgi to serve Python scripts) But I don't think messing up with environment variable is 'clean' enough.
Can anyone suggest me a better solution?
First thing you can do is set up those variables in your project's settings module, many apps do that:
# settings
BLOG_TITLE = 'My title'
Then, a good practice is to provide settings defaults, so your app should have a settings file
# blog/settings.py
from django.conf import settings
BLOG_TITLE = getattr(settings, 'BLOG_TITLE', 'MY default title')
# Then wherever, views or context processor
from blog import settings # See how we're not importing project's settings
title = settings.BLOG_TITLE
Another alternative is to create a "Blog" model that contains all those variables, this may invite you to make your app to have a blog tied per Django sites
from django.contrib.sites.models import Site
class Blog(models.Model):
site = models.OneToOneField(Site) # Tied up to a Django site
title = models.CharField(max_length=256)
Now you can change those values from your Admin interface and use them in your views or context processor
site = Site.objects.get_current() # Installed Django Sites app and middleware
blog = site.blog
print blog.title
You can create settings or constants file in your app folder and use it. This way all your constants will be bound to your application:
apps/
blog/
__init__.py
models.py
urls.py
constants.py # <-- here it is!
File can look like this:
BLOG_TITLE = 'My super blog'
# ...
And you can use tour constants like this:
import blog.constants
# ...
return render_to_response('index.html', {title: blog.constants.BLOG_TITLE})
And in template:
<title>{{ title }}</title>
In my opinion, the best way to do this is by adding a model related to Site model using inheritance
First add site id to your Django settings file
SITE_ID = 1
now create a model in an app
from django.db import models
from django.contrib.sites.models import Site
class Settings(Site):
field_a = models.CharField(max_length=150, null=True)
field_b = models.CharField(max_length=150, null=True)
class Meta:
verbose_name_plural = 'settings'
db_table = 'core_settings' # core is name of my app
def __str__(self) -> str:
return 'Settings'
then edit apps.py file of that app
from django.apps import AppConfig
from django.db.models.signals import post_migrate
def build_settings(sender, **kwargs):
from django.contrib.sites.models import Site
from .models import Settings
if Settings.objects.count() < 1:
Settings.objects.create(site_ptr=Site.objects.first())
class CoreConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'project.apps.core'
def ready(self) -> None:
post_migrate.connect(build_settings, sender=self)
now every time you run migrations a row will auto-generated in core_settings that have a one to one relationship with your Site model
and now you can access to your settings like this
Site.objects.get_current().settings.access_id
optional: if have only a single site
unregister site model from admin site and disable creating and deleting settings model in admin panel
from django.contrib import admin
from . import models
from django.contrib.sites.models import Site
admin.site.unregister(Site)
#admin.register(models.Settings)
class SettingAdminModel(admin.ModelAdmin):
def has_delete_permission(self, request,obj=None) -> bool:
return False
def has_add_permission(self, request) -> bool:
return False