How to fix "name 'self' is not defined" for a Django Singleton Model

293 Views Asked by At

I'm trying to create an editable Help page for users on my website using Django v1.11 and Trumbowyg. What I'm trying to accomplish is:

  1. Only allowing a superuser to edit the page via a button visible to them
  2. Using the Trumbowyg editor to enter and edit the text
  3. Saving that text and then displaying it as html on the page

Naturally, I thought that I should create a model for the HelpText which would hold the text put into the Trumbowyg editor. However, this model would have to be special in that there can only be one of them. So I turned to the Singleton Model. I followed this tutorial and created a SingletonModel model and subclassed it for my HelpText model like so.

class SingletonModel(models.Model):

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        self.pk = 1
        super(HelpText, self).save(*args, **kwargs)


    def delete(self, *args, **kwargs):
        pass

    @classmethod
    def load(cls):
         obj, created = cls.objects.get_or_create(pk=1)
         return obj

class HelpText(SingletonModel):
    text = models.TextField(blank=True)

However, after registering HelpText to my admin.py this gave me an error.

the model s is abstract so it cannot be registered with admin.' model.__name__

From a couple of google searches, I found that the problem was that in class Meta, abstract is set to true. I could not figure out how to get rid of this error so instead I thought, "Hey! If the problem is that abstract is set to true then lets nuke the SingletonModel class completely and just put its methods into HelpText." So then I did this.

class HelpText(models.Model):

    text = models.TextField(blank=True)

    def save(self, *args, **kwargs):
        self.pk = 1
        super(HelpText, self).save(*args, **kwargs)


    def delete(self, *args, **kwargs):
        pass

    @classmethod
    def load(cls):
        obj, created = cls.objects.get_or_create(pk=1)
        return obj

    def __str__(self):
        return self.help_text

Surprisingly, I got an error for this too but of a crueler variety. Now, Django is telling me when I load my help page that "name 'self' is not defined." I have no idea how this is possible considering that I have several other models that use def__str__(self) to define their string methods and blatantly use self to refer to its own fields. How is this happening? The error also occurs in the help_landing method in views.py on the line help_text = webapp_models.HelpText.load(). The views and templates relevant to this model are below.

views.py

@login_required(login_url=LEADER_LOGIN_URL)
def help_landing(request):
    # Variable to decide if the edit button exists on the help_landing page
    super_can_edit = is_superuser(request.user)
    help_text = webapp_models.HelpText.load()

    context = {
        'include_back': True,
        'include_home': True,
        'description': 'Help',
        'super_can_edit': super_can_edit,
        'help_text': help_text,
    }

    return render(request, 'leader/help_landing.html', context)

@login_required(login_url=LEADER_LOGIN_URL)
def help_create_landing(request):
    help_text = webapp_models.HelpText.load()

    context = {
        'include_back': True,
        'include_home': True,
        'description': 'Help Edit',
        'help_text': help_text,
    }

    return render(request, 'leader/help_create_landing', context)

@login_required(login_url=LEADER_LOGIN_URL)
def help_create(request):

    help_text = webapp_models.HelpText.load()

    help_text.update(
        text=request.POST['text'],
        )

    help_text.save()

    return redirect('leader/help_landing')

help_landing.html

{% extends "leader/base.html" %}

{% block extra_css %}
<style>

button {
    background-color: Transparent;
    background-repeat: no-repeat;
    border: none;
    cursor: pointer;
    overflow: hidden;
    outline: none;
}

</style>
{% endblock %}

{% block description %}{{ description }}{% endblock %}

{% block content %}

<div class="ui grid"> 
    <div class="eight wide column"> 
        {% if help_text %}{{ help_text.text }}{% endif %}
    </div>
    {% if super_can_edit %} 
    <div class="six wide column"> 
        <a href="leader/help_create_landing/"> 
            <button class="customButton" type="submit">
              <h2 class="ui header">
                  <i class="big circle add icon"></i>
                    Edit Help Page
              </h2>
            </button>
        </a>
    </div>
    {% endif %}

</div>

{% block javascript %}
<script>

</script>
{% endblock %}

help_create_landing.html

{% extends "leader/base.html" %}

{% block extra_css %}
<style>

button {
    background-color: Transparent;
    background-repeat: no-repeat;
    border: none;
    cursor: pointer;
    overflow: hidden;
    outline: none;
}

</style>
{% endblock %}

{% block description %}{{ description }}{% endblock %}

{% block content %}

<div class="column">
    <form name="helpForm" action="/leader/help_create/" method="post" role="form" enctype="multipart/form-data">{% csrf_token %}
        <div class="ui grid"> 
            <div class="six wide column"> 
                <textarea id="helpEditor" name="text" rows=6 type="text">
                    {% if help_text %}{{ help_text.text }}{% endif %}
                </textarea>
            </div>
            <div class="six wide column"> 
                <button type="submit" id="save">Edit</button>
            </div>
        </div>
    </form>
</div>

{% block javascript %}
<script>
    $(helpEditor).trumbowyg();
</script>


{% endblock %}

Traceback: I'm switching out the website name for security reasons

Environment:


Request Method: GET
Request URL: https://fdev.com/leader/help_landing/

Django Version: 1.11.4
Python Version: 3.5.2
Installed Applications:
['webapp.apps.WebappConfig',
 'leader.apps.LeaderConfig',
 'rest_framework',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'channels']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/home/felix/felix_env/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/home/felix/felix_env/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/felix/felix_env/lib/python3.5/site-packages/channels/handler.py" in process_exception_by_middleware
  243.             return super(AsgiHandler, self).process_exception_by_middleware(exception, request)

File "/home/felix/felix_env/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/felix/felix_env/lib/python3.5/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  23.                 return view_func(request, *args, **kwargs)

File "/home/felix/felixserver/leader/views.py" in help_landing
  1892.     help_text = webapp_models.HelpText.load()

File "/home/felix/felixserver/webapp/models.py" in load


Exception Type: NameError at /leader/help_landing/
Exception Value: name 'self' is not defined

When in the Django shell, I can instantiate a HelpText object but if I create more than one I get an error. I believe this is because I made sure that there should always be one HelpText model existing. Here's the traceback.

Traceback (most recent call last):
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 328, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: UNIQUE constraint failed: webapp_helptext.id

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/query.py", line 394, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/felix/felixserver/webapp/models.py", line 371, in save
    super(HelpText, self).save(*args, **kwargs)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/base.py", line 807, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/base.py", line 837, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/base.py", line 923, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/base.py", line 962, in _do_insert
    using=using, raw=raw)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/query.py", line 1076, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1107, in execute_sql
    cursor.execute(sql, params)
File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/backends/utils.py", line 80, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/home/felix/felix_env/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 328, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: webapp_helptext.id
0

There are 0 best solutions below