I created a very simple example code using Django, but cannot get model value to be displayed on my page:
----------------------------- home/models.py
from django.db import models
class Home(models.Model):
msg = models.CharField(max_length=100)
#classmethod
def create(cls, msg):
home = cls(msg=msg)
# do something with the book
return home
home = Home.create("Hello World!")
------------------------------------home/views.py
from django.views.generic import TemplateView
from project.models import Home
class IndexView(TemplateView):
model = Home
template_name = 'home/index.html'
------------------------------------------ templates/home/index.html
{{ home.msg }}
this is a test page. I am expecting to see this....
------------------------------------------- urls.py
from django.conf.urls.defaults import patterns, include, url
from django.contrib import admin
from django.views.generic import TemplateView
admin.autodiscover()
urlpatterns = patterns('',
# Home pagetentacl.urls
url(r'^$', TemplateView.as_view(template_name='home/index.html')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
)
-------------------------------------- result page on browser:
this is a test page. I am expecting to see this....
I don't want to have DB access for my example. I want my model returns "hello world" string. home.msg on index.html doesn't return anything. What is missing here?
You're not giving the template an instance of Home. You need to create one and pass it to the template as a Context, in the form {'msg': msg}.
EDIT: Adding some code
First of all, you should create your instance of home in your view. I've never used TemplateViews, so I'm going to use a regular view method instead.
def IndexView(request):
home=Home.create("Hello World!")
return render(request, 'index.html', {'home': home},)
As #Daniel rightly points out, you're not giving your template an instance of Home to work with.
If you want to use class-based views, subclass TemplateView and override get_context_data():
class IndexView(TemplateView):
template_name = "home/index.html"
def get_context_data(self, **kwargs):
context = super(HomePageView, self).get_context_data(**kwargs)
context["home"] = Home.create("Hello World!")
return context
And make sure your urls.py is using IndexView.as_view() - your version above is just referencing the generic TemplateView.
The fact that you added a model field to your subclass of TemplateView makes me think you're confusing it with DetailView. See the documentation for the difference.
Related
I am using Django 3.2 and django-allauth 0.44
I have set my LOGIN_REDIRECT_URL in settings.py as follows:
LOGIN_REDIRECT_URL = 'profile-page'
in urls.py, I have the following route defined:
path('accounts/profile/slug:username', AccountProfileView.as_view(), name='profile-page'),
When I log in, (unsurprisingly), I get the following error message:
NoReverseMatch at /accounts/login/
Reverse for 'profile-page' with no arguments not found. 1 pattern(s) tried: ['accounts/profile/(?P[-a-zA-Z0-9_]+)$']
How do I pass (or specify) a parameter of the logged in user's username to the route?
If your view needs to perform redirects which are not very simple, you need to override the get_success_url method, considering that you use django-allauth, you will need to override allauth.account.views.LoginView and also write your own url pattern for it so that your overriden view is used. First override the view:
from django.urls import reverse
from allauth.account.views import LoginView as AllauthLoginView
from allauth.account.utils import get_next_redirect_url
class LoginView(AllauthLoginView):
def form_valid(self, form):
self.user = form.user # Get the forms user
return super().form_valid(form)
def get_success_url(self):
ret = (
get_next_redirect_url(self.request, self.redirect_field_name)
or reverse('profile-page', kwargs={'username': self.user.username})
)
return ret
Next wherever you define the urls for allauth, just add your own url before it:
from path_to.view_above import LoginView # Change this import properly
urlpatterns = [
...
path('accounts/login/', LoginView.as_view(), name="account_login"),
path('accounts/', include('allauth.urls')),
...
]
Another alternative solution using allauth is to use a custom ACCOUNT_ADAPTER and override it's get_login_redirect_url because LoginView will internally call it in case there is no next parameter. To do this, first inherit from allauth.account.adapter.DefaultAccountAdapter:
from django.urls import reverse
from allauth.account.adapter import DefaultAccountAdapter
class MyAccountAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
return reverse('profile-page', kwargs={'username': request.user.username})
Next in settings.py set ACCOUNT_ADAPTER:
ACCOUNT_ADAPTER = "path.to.MyAccountAdapter"
The LOGIN_REDIRECT_URL should point to the page on which user lands after he successfully logs into your website, unless he was redirected to the login page by trying to visit any of the pages that require the authorization.
If you want to redirect user to a specific page, in this example to his own profile page, you can create an intermediate URL that will redirect the user to his own profile page, when visited. It can be accomplished like so:
Using class-based views:
class CurrentUserProfileRedirectView(LoginRequiredMixin, RedirectView):
def get_redirect_url(self, *args, **kwargs):
return reverse('profile-page', kwargs={'username': request.user.username})
or using function-based views:
#login_required
def current_user_profile(request):
return redirect('profile-page', username=request.user.username)
Next, register this redirect view as a regular view, not requiring any parameters, and set the LOGIN_REDIRECT_URL to this view's name.
I'm building a project in Django starting with DjangoX and am simply trying to get the currently logged in username or userid. I've tried all kinds of combinations and approaches, some of them I've left in comments, based on other on-line questions and answers and not getting this to work.
views.py:
from django.views.generic import TemplateView, CreateView
from requests import request # <-- tried this, didn't help got AttributeError no 'user'
from django.contrib.auth import get_user_model
from django.conf import settings
class HomePageView(TemplateView):
# get user model and current user information
umodel = get_user_model()
# current_user = request.user # produces NameError: name 'request' is not defined
# u = user # get error that user is not defined
# u = umodel.id # <django.db.models.query_utils.DeferredAttribute...blah blah blah>
template_name = 'pages/home.html'
...
in my .html file, I can use this to display exactly what I'm trying to access in my View!
home.html (this works)
<p>user = {{ user }}</p>
<p>user.id = {{ user.id }}</p>
urls.py
...
urlpatterns = [
path('', IndexPageView.as_view(), name='index'),
path('home/', HomePageView.as_view(), name='home'),
...
This is a class-based view. You can't write request-dependent code at class level. Either switch to a function-based view, or put that code into the get_context_data method.
I am trying to implement on my website a simple and friendly address system.
What i'm thinking about is when the user logged in, his username will be displayed in the address bar.
www.example.com/username1 (for home page profile)
www.example.com/username1/about/
www.example.com/username1/gallery/
www.example.com/username2 (for home page profile)
www.example.com/username2/about/
www.example.com/username2/gallery/
And additionally if anyone enter the address www.example.com/username1, will be shown the profile of user1.
I already implemented a register/Login system using Django-Allauth
mySite/urls.py
url(r'^accounts/', include('allauth.urls')),
home/urls.py
url(r'^$', views.index),
home/views.py
def index(request):
return render_to_response('home/index.html', context_instance=RequestContext(request))
I tried to follow some examples like Facing problem with user profile url scheme like example.com/username in django
But i dont have this thing working yet. I dont understand what to do :(
Please, give some advise.
Add the following url as the last item of the mySite/urls.py:
urlpatterns = patterns('',
...
url(r'^(?P<username>\w+)/', include('userapp.urls')),
)
Then the username parameter will be passed to the views of your userapp:
userapp/urls.py:
from userapp import views
urlpatterns = patterns('',
url(r'^$', views.profile, name='user_profile'),
url(r'^about/$', views.about, name='user_about'),
url(r'^gallery/$', views.gallery, name='user_gallery'),
)
userapp/views.py:
def profile(request, username):
user = get_object_or_404(User, username=username)
return render(request, 'userapp/profile.html', {'profile_user': user})
def about(request, username):
...
def gallery(request, username):
...
It's almost perfect, but i have a bug. Let me explain. When i login (my login system is: django-allauth) on the http://127.0.0.1:8000/accounts/login/ i return to http://127.0.0.1:8000 with an error 404.
I am not getting the http://127.0.0.1:8000/username/ with the template, when the login botton is clicked.
The instalation of django-allauth require adding to the settings.py
LOGIN_REDIRECT_URL = '/'
How can i redirect to http://127.0.0.1:8000/username/ and show the correct template?
1. Regarding
How can i redirect to
Based on the answer from https://stackoverflow.com/a/20143515/4992248
# settings.py:
ACCOUNT_ADAPTER = 'project.your_app.allauth.AccountAdapter'
# project/your_app/allauth.py:
from allauth.account.adapter import DefaultAccountAdapter
class AccountAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
return 'request.user.username' # probably also needs to add slash(s)
Would be better to use get_absolute_url, ie return 'request.user.get_absolute_url'. In this case you need to do:
# 1. Add `namespace` to `yoursite/urls.py`
urlpatterns = patterns('',
...
url(r'^(?P<username>\w+)/', include('userapp.urls', namespace='profiles_username')),
)
# 2. Add the code below to the Users class in models.py
def get_absolute_url(self):
# 'user_profile' is from the code shown by catavaran above
return reverse('profiles_username:user_profile', args=[self.username])
2. Regarding
show the correct template
catavaran wrote correct urls which leads to views.profile, so in view.py you need to write:
from django.shortcuts import render
from .models import UserProfile # import model, where username field exists
from .forms import UserProfileForm # import Users form
def profiles(request, username):
user = get_object_or_404(UserProfile, username=username)
return render(request, 'home/profiles.html', {'user_profile_form': user})
In template (i.e. profiles.html) you can show user's data via {{user_profile_form.as_p}}
I'm new to django. Problem: to see my homepage (that shows the default django login form)
i have to write the addess:
x.x.x.xxx:8001/login
I would like to access it directly through that:
x.x.x.xxx:8001
What i can see now if i digit x.x.x.xxx:8001, is the login page without the form.
I have:
in my urls.py:
urlpatterns = patterns('',
url(r'^$', 'license.views.index', name='auth_login'),
in my views.py
from django import template
from django.shortcuts import render_to_response
from django.views.decorators.vary import vary_on_cookie
#vary_on_cookie
def index(request):
return render_to_response('login.html', {
}, context_instance = template.RequestContext(request))
That is because you are not passing a login form instance to your form.
Unless you want to perform some custom stuff in your view, your best bet is to use Django's built-in login view. You can set a custom template for it:
url(r'^$', 'django.contrib.auth.views.login', {'template_name': 'login.html'})
See this page for more info: django.contrib.auth.views.login (v1.5) docs
Now, I see that you are using a decorator on your view, which implies that you do indeed want to perform custom stuff. In that case, I believe you'll want to use the django.contrib.auth.forms.AuthenticationForm. Try doing something like this in your view:
from django.contrib.auth.forms import AuthenticationForm
from django.shortcuts import render
from django.views.decorators.vary import vary_on_cookie
#vary_on_cookie
def index(request):
form = AuthenticationForm(data=request.POST or None)
return render(request, 'login.html', {
'form': form
})
I am making a blog app where I want to make a view that displays all the blogs of a particular user. For this I need to pass the user instance to my view as
def blogs(request,author=None,slug=None):
# If the author context has been passed then display the blogs of that author
if author:
# Displays a particular blog
if slug:
this_blog = get_object_or_404(Entry, creator = author, slug = slug)
return render_to_response('blog/blog_view.html', {'blog': this_blog,},context_instance=RequestContext(request))
# Displays all the blogs of a particular user
else:
blog_list = Entry.objects.filter(creator = author)
return render_to_response('blog/all_blogs_user.html', {'Blogs': blog_list},context_instance=RequestContext(request))
Although syntactically this is correct but now I do not how to actually pass this user context in my url. Earlier I tried passing just the user id but that does not work. Is there any other alternative to doing this thing. When I am building the url internally or redirecting to this particular view then it is fine, but how would the url look like externally. My urls.py is as
from django.conf.urls.defaults import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
url(r'^$', 'blog.views.blogs', name='all_blogs'),
url(r'^(?P<author>\d+)/(?P<slug>[-\w]+)/$', 'blog.views.blogs', name='view_blog'),
url(r'^(?P<author>\d+)/(?P<slug>[-\w]+)/edit/$', 'blog.views.post_form', name='edit_blog'),
url(r'^new/$', 'blog.views.post_form', name='new_blog'),
url(r'^(?P<author>\d+)/(?P<slug>[-\w]+)/delete/$', 'blog.views.delete_blog', name='delete_blog'),
)
urlpatterns += staticfiles_urlpatterns()
It generally works like this:
urls.py
url(r'/author/(?P<slug>/$', 'author_index'),
views.py
def author_index(request, slug):
author = get_object_or_404(User, username=slug)
return render_to_response('author_index.html', {
'author': author,
}, context_instance=RequestContext(request))
You can simply access the user in the view by request.user. Similarly, you can POST data in the request object as well.