简体   繁体   中英

Django ImportError: cannot import name 'x'

I have problems with circularity in my two files. Model import function to run when create object and this function import model to check if code in unique.

How use model in function and function in model without problem with circularity? I checked questions simillar to my problem but i still don't know to fix this issue.

models.py

from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.db import models
from .middleware.current_user import get_current_user
from shortener.utils import create_shortcode
from django.conf import settings
CODE_MAX_LENGTH = getattr(settings, 'CODE_MAX_LENGTH', 16)


class Shortener(models.Model):
    url = models.URLField()
    code = models.CharField(unique=True, blank=True, max_length=CODE_MAX_LENGTH)
    author = models.ForeignKey(User, blank=True, null=True)  # Allow anonymous
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    active = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        if not self.pk:
            self.author = get_current_user()

            if self.code in [None, ""]:
                self.code = create_shortcode()
            elif self.code.find(' ') != -1:
                self.code = self.code.replace(' ', '_')

            if self.url not in ["http", "https"]:
                self.url = "http://{0}".format(self.url)

        super(Shortener, self).save(*args, **kwargs)

    def __str__(self):
        return self.url

    def __unicode__(self):
        return self.url

    def get_short_url(self):
        return reverse("redirect", kwargs={'code': self.code})

Utils.py

import random
import string
from django.conf import settings
from shortener.models import Shortener
SIZE = getattr(settings, 'CODE_GENERATOR_MAX_SIZE', 12)


def code_generator(size=SIZE):
    return ''.join(random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits) for _ in range(size))


def create_shortcode():
    code = code_generator()

    if Shortener.objects.filter(code=code).exists():
        create_shortcode()

    return code

Traceback:

Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x037EAB28>
Traceback (most recent call last):
  File "C:\Users\loc\shortener\lib\site-packages\django\utils\autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\loc\shortener\lib\site-packages\django\core\management\commands\runserver.py", line 113, in inner_run
    autoreload.raise_last_exception()
  File "C:\Users\loc\shortener\lib\site-packages\django\utils\autoreload.py", line 249, in raise_last_exception
    six.reraise(*_exception)
  File "C:\Users\loc\shortener\lib\site-packages\django\utils\six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\loc\shortener\lib\site-packages\django\utils\autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\loc\shortener\lib\site-packages\django\__init__.py", line 27, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Users\loc\shortener\lib\site-packages\django\apps\registry.py", line 108, in populate
    app_config.import_models(all_models)
  File "C:\Users\loc\shortener\lib\site-packages\django\apps\config.py", line 199, in import_models
    self.models_module = import_module(models_module_name)
  File "E:\Python\Python35-32\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "C:\Users\loc\PycharmProjects\DjangoURLShortener\shortener\models.py", line 4, in <module>
    from shortener.utils import create_shortcode
  File "C:\Users\loc\PycharmProjects\DjangoURLShortener\shortener\utils.py", line 4, in <module>
    from shortener.models import Shortener
ImportError: cannot import name 'Shortener'

Short answer: Move the create_shortcode implementation into the models.py module, it's just 3 lines of code to generate codes in there and you avoid the circular imports. Do the filters inside the model and Shortener.save method with self.objects.filter(...) .

Longer answer: The uuid module and the uuid.uuid4 function is better (than writing a possibly buggy implementation yourself) for generating unique codes. You are, at the moment, generating 12-character or 12-byte random codes, and the UUID module can generate 16-byte codes for you out of the box. If you want enable user-definable or overridable codes but wish to generate very unique codes automatically:

code = models.CharField(unique=True, max_length=16, default=uuid.uuid4)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM