Getting user defined urls in django - django

I would like to add to my app a way for users to create their own url. So, what I mean by this, is that if a user wants to go to their webpage, they could go to http://www.projectdomain.com/JimmyJohn
In my model I have
class Person(models.Model):
username = models.CharField(max_length=30) #username = JimmyJohn
....
Is the best way to do this by just adding a method that catches everything after / in urls.py? Or is there a way to more tightly integrate my models with the urls.py?

Just add a url to your main urls.py accepting a first alphabetic argument (consider adding any other urls of your app above this, and validating usernames so your urls are not valid usernames):
urlpatterns = patterns('',
# ... other fixed urls before
url(r'^(\w+)/$', 'website.views.user_page', name='user_page'),
)
Then query for a User in your view matching the given username:
def user_page(request, username):
user = get_object_or_404(User, username=username)
return render(...)

Related

Fetching users data based on username input in urls

I am little bit new to django and was working on my first instagram clone project all by myself. I got confused in a place where I needed to fetch user data based on 127.0.0.1:8000/username and I found a useful but useless answer(for me) from medium(.com) .The author was using class based view. In class based view, I didnot get any documentation to use multiple models as much as I searched so i had to do it with function based view as I have not learned class based view yet.I had to use post model, profile model and User model to get data for profile page.
This is the code that somehow worked but should I use this view?
from django.contrib.auth.models import User
from .models import Profile
#profile view
def profile_data(request, username):
mydata = User.objects.get(username=username)
myprofile = Profile.objects.filter(user=mydata)
mycontext ={'profile': myprofile}
return render(request,'firstapp/profile.html', context=mycontext)
#in urls.py,
from firstapp import views
path('<str:username>/', views.profile_data , name='profile'),
#in models.py,
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,unique=True)
fullname = models.CharField(max_length=100)
def __str__(self):
return self.fullname
In firstapp/profile.html,
<a href="#" class="text-3xl mt-5 text-center">{{user.profile.fullname}}
But I got confused on how to attatch my Profile model in it. So I created this, my own function-based view for it after few hours of researching . Is this ok to use or will give any error in my back? Thank you
I am expecting to get new ways or the correction or additon in my code if possible.
It seems ok, but be careful about the url part, because you will have problems when adding new urls (eg: /login) because it might be treated as a username.
You could get away by editing the order in your urlpatterns so the profile page is the last but now you have an issue if a user has the same username as a url in your page.
For example if a user has "login" as username, you won't be able to go to their profile page.
A solution is to use a prefix for the profile pages (eg: /u/<username> or /#<username>).
Some other improvements:
mydata = User.objects.get(username=username)
myprofile = Profile.objects.filter(user=mydata)
Can be rewriten with only one request:
user = User.objects.get(username=username).select_related("profile")
myprofile = user.profile
See the documentation for select_related: https://docs.djangoproject.com/en/4.1/ref/models/querysets/#select-related
You should also handle the case where the user is not found:
try:
user = User.objects.select_related("profile").get(username=username)
except User.DoesNotExist:
raise Http404("No User matches the given query.")
myprofile = user.profile

Django-Allauth, Multiple login redirect url

I have a question, how can I add more than one LOGIN_REDIRECT_URL in settings or in views for my differents users.
For example, I have: Administrators, Human Resources, Teachers, students... etc
and for each I need redirect to a different url, panel admin for Admin etc.
I need add groups? or not?
Thanks for your help!
django-allauth get the login redirect URL from method get_login_redirect_url defined in account adapter you can define your custom adapter and override this:
my_app/adapter.py
from allauth.account.adapter import DefaultAccountAdapter
class AccountAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
url = super(AccountAdapter, self).get_login_redirect_url(request)
user = request.user
'''
# pseudocode, change it to actual logic
# check user role and return a different URL
role = get_user_role(user)
if role == 'student':
url = student_login_redirect_url
if role == 'teacher':
url = teacher_login_redirect_url
'''
return url
Now tell allauth to use our custom adapter by defining the ACCOUNT_ADAPTER in settings.py:
ACCOUNT_ADAPTER = 'my_app.adapter.AccountAdapter'

Doing User Profiles In Django

I'm trying to set up user profiles in my site so we have:
www.example.com/someuser
www.example.com/anotheruser2
in my urls.py
url(r'^(?P<profile>[0-9A-Fa-f]{1,36})/', 'site.views.profile),
and my view:
def profile(request, profile):
... do something ...
There are two questions:
Is this the correct way to do this or is there a better way?
How should I handle other urls, like "aboutus", etc.
For Point 2, I would do:
url(r'^aboutus/', 'site.views.aboutus'),
url(r'^(?P<profile>[0-9A-Fa-f]{1,36})/', 'site.views.profile),
So now profile will be the catchall for everything else in the site, and I have to check for a valid profile then throw a 404 if a password is not found.
Again, is there a better way to do this?
It's not a good idea to use site.views.profile as a catchall. It's not good separation of responsibilities, it shouldn't be its job. How about something like this instead:
url(r'^profile/$', 'site.views.profile_self'),
url(r'^profile/(?P<profile_name>[0-9A-Fa-f]{1,36})/$', 'site.views.profile'),
url(r'^aboutus/', 'site.views.aboutus'),
For the catchall, use a custom 404 page, or you could let the server raise a 404 error.
accounts/models.py
from django.db import models
class User():
def get_profile(self):
return UserProfile.objects.get_or_create(user_id=self.id)
class UserProfile(models.Model):
user = models.OneToOneField(User)
# another fields
accounts/urls.py
url(r'^profile/$', 'site.views.profile'),
accounts/views.py
from django.contrib.auth.decorators import login_required
#login_required
def profile(request):
# get current logged user profile
profile = request.user.get_profile()
this way the user logged only can see his own profile.
and for the point 2, what's wrong with this?
url(r'^about_us/$', 'site.views.about_us'),
--UPDATE--
ah, ok. then, you are right. but why not with the username?
accounts/urls.py
url(r'^(?P<username>[-\w]+)/$', 'site.views.profile'),

Multiple Django admin sites redirects to each other

firstly, sorry if this problem was already solved, but I couldn't find solution anywhere.
I created two admin instances in Django, here's my admin.py sample code:
class ConferenceRoomAdmin(admin.ModelAdmin):
readonly_fields = ('token', 'image_tag')
class ConferenceRoomSuperAdmin(admin.ModelAdmin):
readonly_fields = ('token', 'image_tag')
class ConferenceAdmin(admin.AdminSite):
def get_urls(self):
urls = super(ConferenceAdmin, self).get_urls()
return urls
admin_site = ConferenceAdmin()
admin_site.register(ConferenceContext)
admin_site.register(ConferenceRoom, ConferenceRoomAdmin)
class ConferenceSuperAdmin(admin.AdminSite):
pass
super_admin_site = ConferenceSuperAdmin()
super_admin_site.register(ConferenceRoom, ConferenceRoomSuperAdmin)
and urls.py file:
url(r'^admin/', include(admin.admin_site.urls)),
url(r'^myadmin/', include(admin.super_admin_site.urls)),
url(r'^login/', views.login_view),
url(r'^test/', views.test_view),
I'm able to login to both admin instances, however, if I log into 'myadmin' instance and click on any link (i.e. change password or edit users, etc. etc) I'm redirected to 'admin' site. What may be wrong here?
Thanks in advance!
Try adding a name attribute to the second admin site, like so:
super_admin_site = ConferenceSuperAdmin(name = 'super_admin')
That is the only difference between your code and mine, as far as I can tell.

Django password required views

I have an edit view for editing models objects. I want to make it password protected with a password I generate and put in my model. I don't want to use django Users
Let's say I have something like this:
models.py
class Job(models.Model):
......
job_uuid = models.CharField("UUID", max_length=36, default=make_uuid)
password = models.CharField("password", max_length=36)
views.py
def edit_job(request, job_uuid):
job = get_object_or_404(Job, job_uuid=job_uuid)
job_form = EditJobForm(instance=job)
c = {'job_form': job_form,
}
c.update(csrf(request))
return render_to_response('jobs/edit_job.html', c, context_instance=RequestContext(request))
I wanted to protect this URL with the password from the object. I found this app django-password-required but this app uses one password you set in the settings.py
Any easy package or way to do this?
You can write a decorator that will check if password access is required for edit_job view.
Then decorator can use password from session/cookies to verify the access.
If password does not match or not present, you can redirect to different view to show password form, and store it in session.
Hope this helps.