Главная · Советы  · Воодушевление edit profile html view. Расширенный профайл юзера в Django: редактирование расширенных и встроенных полей через одну форму

Воодушевление edit profile html view. Расширенный профайл юзера в Django: редактирование расширенных и встроенных полей через одну форму

For adding additional properties to the UserProfile table you will need to change a series of changes in

  • UserProfile table class
  • RegisterModel class
  • RegisterView (where you will be adding input for the new field)
  • AccountController/Register action (to read the new input value and use accordingly)

1. Modify your UserProfile class

Here in this example I am adding a new field called "MobileNumber ", have declared it as type string.

Public class UserProfiles { public int UserId { get; set;} public string Email { get; set;} public string FirstName { get; set; } public string LastName { get; set; } public string MobileNumber { get; set; } }

2. Add the additional property(ies) to your RegisterModel.cs

Add the new property in your Model. In this example where we want an extra field while user registration we need to update the RegisterModel class. Add validations if need be.

Public class RegisterModel { public string Email { get; set; } public string Password { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string MobileNumber { get; set; } }

3. Display additional fields on your View

Once you have update the Model you should be able to use the @Html.TextBoxFor(m => m.MobileNumber) in your view, which will bind the MobileNumber field to your "MobileNumber" property declared in your model.

@using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary() @Html.LabelFor(m = m.Email) @Html.TextBoxFor(m => m.Email) @Html.LabelFor(m => m.Password) @Html.PasswordFor(m => m.Password) @Html.LabelFor(m => m.FirstName) @Html.TextBoxFor(m => m.FirstName) @Html.LabelFor(m => m.LastName) @Html.TextBoxFor(m => m.LastName) @Html.LabelFor(m => m.MobileNumber) @Html.TextBoxFor(m => m.MobileNumber) }

4. Update your Controller - (AccountController in this case)

Last step, here you just need to read the value posted to your model and pass it along the repository for saving.

Public ActionResult Register(RegisterModel model) { if (ModelState.IsValid) { // Attempt to register the user try { WebSecurity.CreateUserAndAccount(model.Email, model.Password, new { FirstName = model.FirstName, LastName = model.LastName, MobileNumber = model.MobileNumber }); WebSecurity.Login(model.Email, model.Password); return RedirectToAction("Index", "Home"); } catch (MembershipCreateUserException e) { ModelState.AddModelError("", ErrorCodeToString(e.StatusCode)); } } // If we got this far, something failed, redisplay form return View(model); }

5. Get this value back from DB and into your view

Now since your RegisterModel already has this property and so does your UserProfile class, using RegisterModel class on your view, you should be able to access the new added property.

I have put a section on my website to fill a form of userprofile called profile.html . I have on this moment this models.py to display this information on my admin panel:

I want to enable the possibility of edit this information per user on their respective profile, thereby i can audit the user profile information per user in my admin panel (localhost:8000/admin) what is the good form to create the respective view and it url?

This is my urls.py actually (This isn"t the main urls.py, is an especial urls.py for my app and lack the url for profile)

From django.conf.urls import patterns, include, url urlpatterns = patterns("", url(r"^$","dracoin.apps.home.views.index" ,name="vista_principal"), url(r"^landing/$","dracoin.apps.home.views.landing" ,name="vista_aterrizaje"), url(r"^shop/page/(?P.*)/$","dracoin.apps.home.views.shop" ,name="vista_tienda"), url(r"^card/(?P.*)/$","dracoin.apps.home.views.singleCard",name="vista_single_card"), url(r"^contacto/$","dracoin.apps.home.views.contacto" ,name="vista_contacto"), url(r"^login/$","dracoin.apps.home.views.login_view",name="vista_login"), url(r"^logout/$","dracoin.apps.home.views.logout_view",name="vista_logout"), url(r"^registro/$","dracoin.apps.home.views.register_view",name="vista_registro"),

This is my models.py for profile:

From django.db import models from django.contrib.auth.models import User def url(self,filename): ruta = "MultimediaData/Users/%s/%s"%(self.user.username,filename) return ruta class userProfile(models.Model): name = models.CharField(max_length=30, default="") user = models.OneToOneField(User) photo = models.ImageField(upload_to=url) email = models.EmailField(max_length=75) def __unicode__(self): return self.user.username

My views.py (lack the userProfile view)

From django.shortcuts import render_to_response from django.template import RequestContext from dracoin.apps.synopticup.models import card from dracoin.apps.home.forms import ContactForm,LoginForm,RegisterForm from django.core.mail import EmailMultiAlternatives from django.contrib.auth.models import User from dracoin.settings import URL_LOGIN from django.contrib.auth import login,logout,authenticate from django.http import HttpResponseRedirect from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.contrib.auth.decorators import login_required def index(request): return render_to_response("home/index.html",context_instance=RequestContext(request)) @login_required(login_url=URL_LOGIN) def landing(request): return render_to_response("home/landing.html",context_instance=RequestContext(request)) @login_required(login_url=URL_LOGIN) def shop(request,pagina): lista_tarj = card.objects.filter(status=True) paginator = Paginator(lista_tarj,5) try: page = int(pagina) except: page = 1 try: tarjetas = paginator.page(page) except (EmptyPage,InvalidPage): tarjetas = paginator.page(paginator.num_pages) ctx = {"tarjetas":tarjetas} return render_to_response("home/shop.html",ctx,context_instance=RequestContext(request)) @login_required(login_url=URL_LOGIN) def singleCard(request,id_tarj): tarj = card.objects.get(id=id_tarj) ctx = {"card":tarj} return render_to_response("home/singleCard.html",ctx,context_instance=RequestContext(request)) @login_required(login_url=URL_LOGIN) def contacto(request): info_enviado = False # Define si se envio la informacion o no email = "" titulo = "" texto = "" if request.method == "POST": formulario = ContactForm(request.POST) if formulario.is_valid(): info_enviado = True email = formulario.cleaned_data["Email"] titulo = formulario.cleaned_data["Titulo"] texto = formulario.cleaned_data["Texto"] # Configuracion de enviado de correos vis hotmail to_supp = "[email protected]" html_content = "Informacion recibida


***Mensaje***

%s



%s

%s"%(titulo,email,texto) msg = EmailMultiAlternatives("Correo de Contacto",html_content,"[email protected]",) msg.attach_alternative(html_content,"text/html") # Contenido definido como html msg.send() else: formulario = ContactForm() ctx = {"form":formulario,"email":email, "titulo":titulo, "texto":texto, "info_enviado":info_enviado} return render_to_response("home/contacto.html",ctx,context_instance=RequestContext(request)) def login_view(request): mensaje = "" if request.user.is_authenticated(): return HttpResponseRedirect("/") else: if request.method == "POST": form = LoginForm(request.POST) if form.is_valid(): next = request.POST["next"] username = form.cleaned_data["username"] password = form.cleaned_data["password"] usuario = authenticate(username=username,password=password) if usuario is not None and usuario.is_active: login(request,usuario) return HttpResponseRedirect(next) else: mensaje = "user or password aren"t correct" next = request.REQUEST.get("next") form = LoginForm() ctx = {"form":form,"mensaje":mensaje,"next":next} return render_to_response("home/login.html",ctx,context_instance=RequestContext(request)) def logout_view(request): logout(request) return HttpResponseRedirect("/") def register_view(request): form = RegisterForm() if request.method == "POST": form = RegisterForm(request.POST) if form.is_valid(): first_name = form.cleaned_data["first_name"] usuario = form.cleaned_data["username"] email = form.cleaned_data["email"] password_one = form.cleaned_data["password_one"] password_two = form.cleaned_data["password_two"] u = User.objects.create_user(first_name=first_name,username=usuario,email=email,password=password_one) u.save() return render_to_response("home/thanks_register.html",context_instance=RequestContext(request)) else: ctx = {"form":form} return render_to_response("home/register.html",ctx,context_instance=RequestContext(request)) ctx = {"form":form} return render_to_response("home/register.html",ctx,context_instance=RequestContext(request))

Def edit_profile(request): user = request.user user_profile = user.userprofile if request.method == "POST": user_profile_form = userProfile(request-POST) if user_profile_form.is_valid(): update user profile else: user_profile_form = userProfileForm(instance=user_profile) variables = RequestContext(request,{"user_profile_form" : user_profile_form}) return render_to_response("home/edit_profile.html", variables)

User-agent styles are displayed against a different background, and the link to the filename and line number contains the prefix (user agent) :

element {} rule

The element {} rule at the top of the rules list isn"t actually a CSS rule. It represents the CSS properties assigned to the element via its style attribute.

Starting in Firefox 52, this also gets the target icon: , giving you a convenient way to highlight the currently selected element in the page.

Filtering rules

There"s a box at the top of the Rules view labeled "Filter Styles":

As you type:

  • any rules which don"t contain the typed string at all are hidden
  • any declarations which contain the typed string are highlighted

Click the "X" at the end of the search box to remove the filter.

While in the Rules view, you can press Ctrl / Cmd + F to focus the search field. Once you"ve typed in a filter, you can press Esc to remove it again.

Strict search

By default, the search box highlights all declarations which contain any part of the string. For example, searching for "color" will highlight declarations containing border-bottom-color and background-color as well as just color .:

If you enclose the search query in ticks, like this: `color`, the search is restricted to exact matches:

Expanding shorthand properties

If you set one of these pseudo-classes for a node, an orange dot appears in the markup view next to all nodes to which the pseudo-class has been applied:

Link to CSS file

At the top right of each rule, the source filename and line number is displayed as a link: clicking it opens the file in the Style Editor .

You can copy the location of the source file: right-click the link and select "Copy Location".

Overridden declarations

If a CSS declaration is overridden by some other CSS rule with a greater weight, then the declaration is shown with a line through it.

Overridden declarations have a funnel next to them. Click the funnel to filter the rule view to show only the rules applying to the current node that try to set the same property: that is, the complete cascade for the given property.

This makes it easy to see which rule is overriding the declaration:

View @media rules for Print

Beginning with Firefox 68, you can toggle the display into a mode that emulates @media rules for print.

When on, any rules defined for printing the page will be displayed similar to the "Print Preview" mode that many word processing applications provide.

Examine computed CSS

To see the complete computed CSS for the selected element, select the Computed panel in the righthand pane. This panel shows the calculated value that each CSS property has for the selected element:

You can Tab through them to select them, and from Firefox 49 onwards, you can find more information about these properties - pressing F1 on a selected property will open up its MDN reference page.

Clicking the arrow next to the property name (or pressing Enter or Space while it is selected) shows the rule that set this value, along with a link to the source filename and line number:

By default, this view only shows values that have been explicitly set by the page: to see all values, click the "Browser styles" box. You can Tab through the filenames/line numbers; pressing Enter / Return will open up the relevant file at that point in the Style Editor .

Typing in the search box performs a live filtering of the list, so, for example, if you just want to see font-related settings, you can type "font" in the search box, and only properties with "font" in the name will be listed. You can also search for the values of properties: to find the rule responsible for setting the font to "Lucida Grande", type that in the search box.

While in the Computed view, you can press Ctrl / Cmd + F to focus the search field. Once you"ve typed in a filter, you can press Esc to remove it again.

Edit rules

If you click on a declaration or a selector in the Rules view you can edit it and see the results immediately. You can also Tab through the different existing properties and values, and start editing them by pressing Enter or Space . To add a new declaration to a rule, click on the last line of the rule (the line occupied by the closing brace).

As you start typing a property name, you"ll see a list of autocomplete suggestions. Press Tab to accept the current suggestion or Up and Down to move through the list. The default choice is the most common property that starts with the letters you"ve typed. For example, here the user has typed "c" and the default choice is "color":

If you enter an invalid value for a property when editing it, or an unknown property name, a yellow alert icon appears besides the declaration.

Edits that you make in the Rules view are reflected in the Style Editor , and vice versa. Any changes you make are temporary: reloading the page will restore the original styling.

While you"re editing CSS, the context menu you"ll see is the normal one for working with editable text:

CSS variable autocompletion

In addition, hovering over a CSS variable name brings up a tooltip showing what color value is stored in that variable (bug 1431949).

Editing keyboard shortcuts

You can use the arrow and page up/down keys (along with others) to increase/decrease numeric rules while editing:

  • The Up arrow will increment values by 1 - "1px" will change to "2px", for example.
  • Shift + Up / Down will increment values by 10.
  • Alt + Up / Down will increment values by 0.1. Please note that in Firefox 60 this combination changed to Ctrl + Up / Down on Linux and Windows to avoid clashes with default OS-level shortcuts (see bug 1413314). It stayed the same on Mac - Ctrl + Up on macOS is the default shortcut for showing Mission Control.
  • Shift + Page up / Page down will increment values by 100.

Track changes

When you are editing the rules in the rules view, you can see the changes you have made in the Changes pane. (Firefox 65 and later)

Note: You can view changes made to the rules view only. If you edit the CSS using the Style Editor, the changes will not be shown in the changes pane.

Also remember, as noted above, that changes you make to the CSS rules are temporary and will be reset if you reload the page.

Beginning in Firefox 67, if you are satisfied with the changes you have made, you can copy the new settings to page the edited rule into your stylesheet. Right-click on the changes panel and select Copy Rule from the context menu.

The Copy Rule command copies the entire element, class, or id definition, including any unchanged rules and the rules that describe your changes. For example, copying the changes in the preceding image, you get the following:

Text-content p { box-sizing:border-box; max-width:24rem; text-decoration: underline; color: cadetblue; font-weight: bold; }

Add rules

You can add new rules in the Rules view. Just right-click to show the context menu and select "Add rule". This will add a new CSS rule whose selector matches the currently selected node.

There"s also a button that enables you to do the same thing:

Copy rules

To copy rules, and pieces of rules, use one of the following context menu items in the Rules view:

  • Copy Rule
  • Copy Selector
  • Copy Property Declaration
  • Copy Property Name
  • Copy Property Value

See also

  • Complete list of Page Inspector Keyboard shortcuts .
  • The Inspector also includes a number of specialized tools for working with particular CSS features, such as colors, fonts, and animations. To read about these see the list of

в Django я по прежнему новичок, но что-то стараюсь понять и запомнить.

стояла задача расширить профиль пользователя дополнительными полями, статей на эту тему пресс и малелькая тележка, но не получалось, то у кого-то на сайте парсер html сильно злой и код надо было переписывать, у кого-то были ошибки в примерах и т.п.

но как-то оно получилось, попробую собрать все мысли в кучу в эту статью.

{% endblock content %}

сохраняем, теперь можно обратиться к /profiles/edit/ то должно открыться форма редактирования профиля.

бывают ситуации, что в профиле есть какие-то поля, что запрещено редактировать пользователю, реализуется это довольно просто

создаём класс формы, наследуемой от общей формы, в котором перечисляем, то что нам исключить от вывода пользователю
forms.py

from django.db import models
from django.forms import ModelForm

.........
class ProfileForm(forms.ModelForm ) :
class Meta:
model = UserProfile
exclude = ("user" , "last_name" , )

from PROJ.apps.APP.models import UserProfile
проект и приложение где расположена расширенная модель

теперь в urls.py надо указать, что страницу редактирования профиля надо открывать с нужной нам формой

from PROJ.APP .forms import ProfileForm
........
("^profiles/edit" , "profiles.views.edit_profile" , { "form_class" : ProfileForm, } ) ,
(r"^profiles/" , include("profiles.urls" ) ) ,
.......

Должно получиться примерно так.. проверяем на странице редактирования профиля (/profiles/edit/).

Теперь сделаем страницу отображения профиля profile/profile_detail.html

вывести можно что угодно из профиля вот так

< p>< strong> Address 2 :< /strong>< br> { { profile .address2 } } < /p>

где address2 это дополнительное поле
список пользователей с профилями можно вывести вот так

profiles/profile_list.html

{ % extends "base.html" %}
{ % block content %}
< h1> Список пользователей< /h1>
< br/>< br/>
{ % for p in object_list %}
< a href= "{% url profiles_profile_detail p.user %}" > { { p.user } } < /a>
{ % endfor %}
{ % endblock %}

Теперь задача такая, сейчас профиль и пользователь живут почти своей жизнью, при регистрации пользователя профиль сам не создаётся это мы сейчас и решим сигналами.

в models.py добавим

from django.db .models import signals
from bucket.signals import create_profile

# When model instance is saved, trigger creation of corresponding profile
signals.post_save .connect (create_profile, sender= User)

создадим файл, если он не создан signals.py:

def create_profile(sender, instance, signal , created, **kwargs) :
"""When user is created also create a matching profile."""

from PROJ.apps .APP .models import UserProfile

if created:
UserProfile(user = instance) .save ()
# Do additional stuff here if needed, e.g.
# create other required related records

вот и всё, при регистрации нового пользователя автоматически будет создаваться к нему профиль, если у вас уже сейчас много пользователей, то создать для каждого профиль можно вот так

$ python manage.py shell

from django.contrib .auth .models import User
from bucket.models import Profile

Users = User.objects .all ()
for u in users:
try :
p = u.get_profile ()
except p.DoesNotExist :
Profile(user = u) .save ()

ещё коснусь вопроса редактирования своего email в профиль, пока ещё не совсем разобрался с этим.

пока есть только пример, делается это анналогично через forms.py

class ProfileForm(ModelForm) :

def __init__ (self , *args, **kwargs) :
super (ProfileForm, self ) .__init__ (*args, **kwargs)
try :
self .fields [ "email" ] .initial = self .instance .user .email
# self.fields["first_name"].initial = self.instance.user.first_name
# self.fields["last_name"].initial = self.instance.user.last_name
except User.DoesNotExist :
pass

email = forms.EmailField (label= "Primary email" , help_text= "" )

class Meta:
model = Profile
exclude = ("user" , )

def save(self , *args, **kwargs) :
"""
Update the primary email address on the related User object as well.
"""

u = self .instance .user
u.email = self .cleaned_data [ "email" ]
u.save ()
profile = super (ProfileForm, self ) .save (*args, **kwargs)
return profile

надеюсь вернусь к этому вопросу